Commit Graph
295 Commits
Author SHA1 Message Date
Chris Tate ffd760bfa2 Merge main 2026-10-18 04:55:11 -05:00
Chris Tate 5093ab9a7a Add markAsUncloneable and worker[Symbol.asyncDispose] (#1269) 2026-10-18 04:41:04 -05:00
Chris Tate ab1c271dde Support the regex v flag (#1268) 2026-10-18 04:01:38 -05:00
Chris Tate a18335e6c4 Revert "Return a worker's memory when it exits without sharing any of it" (#1267) 2026-10-18 04:00:54 -05:00
Chris Tate a0b1e93dec Merge main 2026-10-18 03:52:20 -05:00
Chris Tate 51777dee63 Add markAsUncloneable and worker[Symbol.asyncDispose]
markAsUncloneable(value) marks a plain object, a record, an error or a
class instance (scr_json.c); structuredClone and postMessage then throw
DataCloneError "Cannot clone object of unsupported type." for it, also
where it is nested. As in Node, the mark has no effect on primitives,
arrays, typed arrays and ArrayBuffers. Marked values are retained until
the thread exits; with nothing marked, the clone paths add one branch.

worker[Symbol.asyncDispose]() terminates the worker and resolves with
undefined after its 'exit' event, so `await using` disposes a Worker at
the end of its block. The Worker handle's symbol_get op answers the
well-known symbol: the symbol unit registers Symbol.asyncDispose with the
dyn core when the program names it, and scr_dyn_is_async_dispose_symbol
tells the worker unit, so worker programs that never name the symbol do
not link the symbol unit.

static-support.json adds rows for markAsUncloneable, isInternalThread
(already lowered as false and declared) and worker[Symbol.asyncDispose]().

Corpus 5990-5991 match Node v24.22.0; corpus-costs.json records their
costs.
2026-10-18 03:43:06 -05:00
Chris Tate d375212a32 Add BroadcastChannel and the remaining Node 24 worker_threads surfaces (#1189) 2026-10-18 03:38:36 -05:00
Chris Tate 84916f25e4 Support the regex v flag
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.
2026-10-18 03:37:40 -05:00
Chris Tate 3fd1d2bde6 Revert "Return a worker's memory when it exits without sharing any of it (#1258)"
This reverts commit 2385fc4fff.
2026-10-18 03:37:07 -05:00
Chris Tate d7ac6d3165 Merge main 2026-10-18 03:17:25 -05:00
Chris Tate 85ed5fdb5a Lower Date.prototype.toJSON with Node's null for invalid dates (#1255) 2026-10-18 02:30:06 -05:00
Chris Tate 7c0db7d2b3 Merge main 2026-10-18 02:07:18 -05:00
Chris Tate fe47b3861f Add Float16Array (#1249) 2026-10-18 02:06:17 -05:00
Chris Tate 2385fc4fff Return a worker's memory when it exits without sharing any of it (#1258) 2026-10-18 01:54:28 -05:00
Chris Tate 9750d3994a Merge main 2026-10-18 01:21:52 -05:00
Chris Tate 9498d93c52 Merge main 2026-10-18 01:18:53 -05:00
Chris Tate b06e06f871 Merge main 2026-10-18 00:53:19 -05:00
Chris Tate 8077a9bfff Add DisposableStack (#1248) 2026-10-18 00:50:48 -05:00
Chris Tate 3f84d6475d Merge main 2026-10-18 00:50:24 -05:00
Chris Tate add07dba3d Return a worker's memory when it exits without sharing any of it
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.
2026-10-18 00:46:59 -05:00
Chris Tate 58e6396a1d Merge main 2026-10-18 00:42:37 -05:00
Chris Tate d6bb761ede Merge main 2026-10-18 00:37:03 -05:00
Chris Tate 6774fe5f08 Merge main 2026-10-18 00:28:33 -05:00
Chris Tate 86f5bc34bc Merge main 2026-10-18 00:26:05 -05:00
Chris Tate 5eb65cf64e Merge main 2026-10-18 00:24:03 -05:00
Chris Tate 3dcb8a1a29 Lower Date.prototype.toJSON with Node's null for invalid dates
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>
2026-10-18 00:12:05 -05:00
Chris Tate 370bf5962d Add the cstring class to library profiles
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>
2026-10-17 23:40:06 -05:00
Chris Tate aa19f948c5 Settle async generator completions on Node's microtask turns
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.
2026-10-17 23:19:15 -05:00
Chris Tate dd44148528 Merge main 2026-10-17 22:52:07 -05:00
Chris Tate 32061e8ba3 Add Float16Array
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.
2026-10-17 22:45:32 -05:00
Chris Tate 82c699b437 Add DisposableStack
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.
2026-10-17 22:40:13 -05:00
Chris Tate bb04c2112e Merge main 2026-10-17 22:32:25 -05:00
Chris Tate f4daa00d5c Merge main 2026-10-17 21:59:33 -05:00
Chris Tate a5c7c09ad3 Add mock.timers to node:test 2026-10-17 20:55:17 -05:00
Chris Tate dfd19cbea6 Give socket 'data' listeners strings after setEncoding
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.
2026-10-17 20:11:58 -05:00
Chris Tate 42906482b6 Compile JavaScript classes like TypeScript classes when their layout or JSDoc types allow it
Fixes #934
Co-authored-by: Alan Leal <33952+alantriesagain@users.noreply.github.com>
2026-10-17 18:44:30 -05:00
Chris Tate 2ba6bfa9cd Merge main 2026-10-17 17:57:22 -05:00
Chris Tate a3b2c24b23 Document the wasm32-wasi runtime pack and fix the SC3003 hint (#1223) 2026-10-17 17:13:16 -05:00
Chris Tate 8fbc1d9b77 Document the wasm32-wasi runtime pack and fix the SC3003 hint
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>
2026-10-17 16:39:20 -05:00
Chris Tate 983058a3a7 Lower Error.isError
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.
2026-10-17 16:26:42 -05:00
Chris Tate 6470c870ef Store unknown and object class fields in checked-dynamic storage
TypeScript class fields declared `unknown` or `object`, also with `null`
or `undefined` or as arrays of those, were refused with SC1090. They now
use the checked-dynamic storage that JavaScript class fields without a
declared type already use. This covers instance fields, static fields and
parameter properties. Fields declared `any` stay refused.

Fixes #1147
Co-authored-by: Alan Leal <33952+alantriesagain@users.noreply.github.com>
2026-10-17 15:47:37 -05:00
Chris Tate 4018a1d957 Compile async functions that suspend only at their awaits to stackless coroutines (#1204) 2026-10-17 15:38:36 -05:00
Malte UblandClaude Opus 5.5 24c54fc5d3 Add Int32[] element contracts
`Int32` from @scriptc/types now also annotates the element type of a
declared number array (`Int32[]`, `readonly Int32[]`, `Array<Int32>`,
`ReadonlyArray<Int32>`) on parameters, variables, class instance fields
and function results. The contract promises that every element stored
into the array, through any reference, is an int32 by construction.

contracts/int32-elements.ts checks it over a whole-program flow graph of
the places array references live (locals, parameters, globals, results,
class field families, record fields, container element slots), with one
node per allocation and per opaque origin. Allocations that can reach an
annotated slot are constrained and every element store into an array that
may be constrained must be range-proven an int32 (SC7002); element copies
constrain their sources by fixpoint; arrays from or escaping to code the
IR does not show refuse the contract (SC7003). Slots only constrained
arrays reach are recorded as IrContracts.int32Elements.

Element reads that find a value through those slots carry the int32
range, `getNumber` reads are integer-or-NaN operands of wrapping sums, and
ToInt32 of any integer-or-NaN operand is branch-free. Holes, missing
indices and length changes keep their JavaScript behavior.

Integer kernels over a 2^20-element array: `(s + a[i]) | 0` 1086 -> 175 ms,
`(Math.imul(h, 31) + a[i]) | 0` 602 -> 150 ms, prefix sums 575 -> 155 ms;
programs without the annotation compile to identical binaries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:08:06 -07:00
Malte UblandClaude Opus 5.5 74a9cfb8cc Compile async functions that suspend only at their awaits to stackless coroutines
Native async bodies whose only suspension points are their own awaits now
compile to LLVM switched coroutines, the lowering WASI async bodies and
native synchronous generators already use. A suspended call keeps a heap
frame of the values live across its awaits instead of a fiber with its own
stack. Bodies that reach other suspension points (async generator
consumption, dyn awaits, node:test subtests), module evaluation bodies,
dyn results, worker and library programs, and Windows keep their fibers.

The emitter selects bodies by emitting them as usual first: that text may
suspend only through await runtime calls and await-call entries, and may
call no function that parks. The coroutine form is then emitted and
checked again. Each await prepares its continuation in the runtime (a
pending promise's waiter list, or one READY-queue turn, continuing in place
exactly where a fiber's hop would) and extracts the settled result after
resuming. The eager prefix runs on the spawner's stack and moves to a fresh
stack near the stack guard, so deep async recursion keeps working.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:29:05 -07:00
Chris Tate 8620fa533a Keep record views of class instances only where a copy is observable (#1188) 2026-10-17 12:30:36 -05:00
Chris Tate 8e507160c4 Add BroadcastChannel and the remaining Node 24 worker_threads surfaces 2026-10-17 11:06:47 -05:00
Chris Tate 23056949da Keep readline's terminal cursor on character boundaries, and merge main 2026-10-17 11:06:19 -05:00
Chris Tate c5d5170e1a Keep record views of class instances only where a copy is observable
A structural type that receives class instances became a checked view
for all of its values, even when nothing could tell a copy from the
original. In tsc-ts this turned ResolvedProjectReference, the redirect
parameter of every module resolution, into a checked-dynamic value.

markIdentityFlows still finds every flow, then keeps a type marked only
when the program can observe the difference:

- values of the type are written through, compared by identity (also
  inside generic functions), used as Set or Map keys or array search
  needles, or passed to whole-object observers or any-value parameters;
- a field the type exposes is written on the source class after
  construction, or is an accessor;
- its values flow into another kept view or class-backed protocol.

Other types stay native records.
2026-10-17 10:34:06 -05:00
Chris Tate a904a552d7 Add the concurrency test option (#1180) 2026-10-17 09:37:02 -05:00
Chris Tate b429d4ca6f Merge pull request #1108 from vercel-labs/ctate/add-messagechannel-receivemessageonport-5d9f36
Add MessageChannel, receiveMessageOnPort and MessagePort transfer
2026-10-17 09:35:15 -05:00