Commit Graph
229 Commits
Author SHA1 Message Date
Chris Tate e646b347de Complete node:os and add path.parse and path.format 2026-10-14 00:25:07 -05:00
Chris Tate 3d68826515 Recover the one-shot cost of lifetime regions (#957) 2026-10-14 00:21:26 -05:00
Chris Tate ea6428bad6 Keep the first elements of small appended arrays in the array's block 2026-10-13 23:36:22 -05:00
Chris Tate 549bb45b0a Implement Promise.allSettled and Promise.any (#951) 2026-10-13 22:55:37 -05:00
Chris Tate d99e97cb70 Merge main into lone surrogate strings 2026-10-13 22:20:07 -05:00
Chris Tate 9067503ab6 Recover the one-shot cost of lifetime regions 2026-10-13 21:53:48 -05:00
Chris Tate 9f541456b7 Merge pull request #955 from vercel-labs/ctate/add-lifetimeregion-scriptc-0621ff
Add LifetimeRegion to @scriptc/experimental
2026-10-13 21:52:20 -05:00
Chris Tate 090ccabb72 Add LifetimeRegion to @scriptc/experimental 2026-10-13 21:12:20 -05:00
Chris Tate 124e3204c1 Merge main into lone surrogate strings 2026-10-13 21:07:27 -05:00
Chris Tate 650517429f Match Node for reflection over typed values seen as unknown (#941) 2026-10-13 20:47:29 -05:00
Chris Tate 2a7bf8b0f1 Lower the rest of the global console (#950) 2026-10-13 20:46:49 -05:00
Chris Tate 844ef14771 Keep lone surrogates in strings 2026-10-13 19:48:11 -05:00
Chris Tate 3459ba4a77 Implement Promise.allSettled and Promise.any 2026-10-13 19:12:53 -05:00
Chris Tate 12e3da9fee Lower the rest of the global console 2026-10-13 18:55:55 -05:00
Chris Tate 947f665896 Store boolean arrays as one byte per element 2026-10-13 18:45:47 -05:00
Chris Tate b13a625c61 Match Node for reflection over typed values seen as unknown 2026-10-13 16:25:15 -05:00
Chris Tate ac64b1d7fd Compile regex literals to native matchers (#931) 2026-10-13 11:58:36 -05:00
Chris Tate 67f59798d2 Support node:console Console instances (#923) 2026-10-13 11:57:56 -05:00
Chris Tate bf40cf4255 Compile regex literals to native matchers 2026-10-13 11:30:19 -05:00
Chris Tate 2b280dd25c Merge main into node:console Console support 2026-10-13 10:54:25 -05:00
Chris Tate 1334a8acd2 Lend arguments to closure bodies and comparators 2026-10-13 10:35:18 -05:00
Chris Tate 8056aafa37 Support node:console Console instances
- Support `new Console(...)` over process stdio and writable streams
- Write `log`/`info`/`debug`/`error`/`warn` output like Node, including `ignoreErrors`
- Mark the `Console` class as partially supported in the compatibility data
2026-10-13 09:15:07 -05:00
Chris Tate 4f44241543 Clarify stream consumer support details
- Describe the consumers' Node Readable scope in the compatibility data
- Renumber the new corpus programs to avoid shared prefixes
2026-10-13 09:13:49 -05:00
Chris Tate 5a7fc7225b Support stream/consumers arrayBuffer
- Support `arrayBuffer()` from `node:stream/consumers`
- Print ArrayBuffer and SharedArrayBuffer values like Node
- Mark the stream consumers as partially supported in the compatibility data
2026-10-13 08:33:55 -05:00
Chris Tate 2c8dccd52b Merge main into the docs rewrite 2026-10-13 07:46:52 -05:00
Chris Tate 5df589706b Skip array state bytes below a hole-free prefix 2026-10-13 02:13:46 -05:00
Chris Tate e5ed06771f Use plain wording in the introduction and READMEs 2026-10-13 00:40:11 -05:00
Chris Tate d316552918 Rewrite docs for a coherent new-user flow 2026-10-13 00:34:50 -05:00
Chris Tate ef25cf119d Prepare v0.3.0 2026-10-12 15:57:06 -05:00
Chris Tate 7e6294ca0f Make scriptc compilation native-only 2026-10-12 12:25:30 -05:00
Chris Tate d75d7a22f0 Prepare v0.2.10 2026-10-12 10:31:02 -05:00
Chris Tate 043c656bbd Merge main into feat/program-lifetime-publication 2026-10-12 09:38:24 -05:00
Chris Tate 7cf57f9ed5 Merge main into feat/acyclic-contract 2026-10-12 08:43:05 -05:00
Chris Tate 85736170ae Merge main into feat/program-lifetime-publication 2026-10-12 08:13:15 -05:00
Chris Tate 0d2bcf9d97 Merge main into feat/acyclic-contract 2026-10-12 08:10:24 -05:00
Chris Tate 88b4e89e55 Merge main into feat/nothrow-try-catch 2026-10-12 08:07:54 -05:00
Chris Tate 83248651e2 Publish Immutable factory arrays only after provable index writes 2026-10-12 02:33:29 -05:00
Malte Ubl fa55ce6b07 Keep the RC entry points of array elements in one shared descriptor
Every SCR_ELEM_REF array stored its element type's retain, release and trace entry points in its own header (24 bytes), so ScrArr was 80 bytes: an 80-byte block for arrays of acyclic elements and a 96-byte block for cycle-capable ones. The three pointers now live in one constant ScrArrOps descriptor per element type, which the compiler emits once per module (@sc_arrops.*) and the runtime keeps static, and the header holds a pointer to it plus a 4-byte `cyc` flag beside `elem` that the inline RC fast paths test. ScrArr is 64 bytes: arrays take 64- and 80-byte blocks.

scr_arr_new_ref(retain, release, trace, cap) becomes scr_arr_new_ops(ops, cap); scr_set_to_arr_ref takes the result's descriptor from its caller instead of building an array from the set's key adapters. The backend names the %ScrArr fields in SCR_ARR_FIELD. The layout change bumps the runtime ABI marker to scr_runtime_abi_v13.
2026-10-11 19:46:48 -07:00
Malte Ubl 2ccb018004 Publish ProgramLifetime graphs with @scriptc/threads: program-lifetime instances count 2^63 until published
Program-lifetime instances were created with rc == SIZE_MAX, which every runtime contract reads as "published": the frozen-object guards throw on stores, postMessage and workerData share the object by pointer instead of cloning it, and the publish walker stops there. So programs that publish could not use ProgramLifetime (SC7007 refused it), and an unpublished instance posted to a worker would have been shared instead of cloned.

They are now created with the midpoint count 2^63 (2^31 on 32-bit targets). Only the class's empty retain and release helpers count references on these types, so nothing ever changes or frees that count; the midpoint keeps even an unpaired generic retain or release away from 0 and SIZE_MAX. Until the program publishes an instance it is an ordinary mutable, thread-local object to every runtime contract: stores succeed, postMessage clones it. Publication marks it SIZE_MAX like any object it reaches (the visited mark, logged and restored when a refusal undoes the publish), after which the frozen guards throw Node's TypeErrors and other threads read it by pointer. No header, extra word, runtime change or new instruction: the count itself is the published mark. The cycle analysis keeps the hierarchies untraced, so the collector never visits an instance, as for every untraced class.

SC7007 no longer refuses program-lifetime classes reachable from a publish() call; it still requires a root class in an executable. Without the marker nothing changes: tsc-ts best-v7 built with and without this change is byte-identical.

Tests: corpus 4634-contract-program-lifetime-publish (Node vs native): program-lifetime hierarchies with parent cycles, maps and sets of them, maps keyed by them and mortal scopes around them, published on the main thread and a worker and read on the other; writes after publication throw on both threads; unpublished instances stay writable; a refused publish leaves visited instances writable; a later publish reaches published and fresh instances; an unpublished instance in workerData is cloned. With the old SIZE_MAX count the program dies at its first constructor store. classes.test.ts covers the count on both pointer widths, the walker and the frozen guard. The contract-program-lifetime-publish diagnostics fixture is removed (the program now compiles). Docs: contracts and limitations pages, @scriptc/types.
2026-10-11 17:07:22 -07:00
Malte Ubl 3c26a85d9c Merge branch 'feat/contract-types' into feat/acyclic-contract 2026-10-11 16:32:31 -07:00
Malte Ubl 3d7e8e731c Merge branch 'feat/contract-types' into feat/nothrow-try-catch 2026-10-11 16:32:27 -07:00
Malte Ubl 5bfe1a6bfd Merge branch 'feat/contract-types' into feat/program-lifetime 2026-10-11 16:32:21 -07:00
Malte Ubl 15af413acd Merge branch 'main' into feat/contract-types 2026-10-11 16:32:00 -07:00
Malte Ubl 4dc638b328 Acyclic: compile explainCycle in the self-hosted compiler; MDX-safe docs
An empty step list literal is typed explicitly so the native compiler
maps it to the step array type, and the positions list avoids braces,
which the docs pipeline would parse as an MDX expression.
2026-10-11 16:30:25 -07:00
Malte Ubl ad2fcfbc27 try/catch discharges NoThrow: handlers take what they catch
The may-throw analysis now models handlers. A throwing operation or call
inside a `try` with a `catch`, or inside a try/catch whose `finally`
never completes normally (it returns, breaks or continues, discarding the
pending exception), adds no seed and no call edge. The catch and finally
bodies are analyzed like any other code, so rethrows and a finally that
re-raises stay exact. Worker programs (a termination request unwinds
through catch) and generator bodies (a `.return()` does too) keep the
conservative answer.

Unreachable statements no longer seed: the frontend's SC9002 trap after a
body that returns from both its try and its catch (or ends in a switch
with a default, or an infinite loop) is dead code. On tsc-ts this drops
14 functions from the may-throw set and 44 pending-exception checks.

A NoThrow function may now contain handled calls; the SC7001 hint names
the remedy that applies (catch it, remove the recursion, or the worker
exception).
2026-10-11 16:30:24 -07:00
Malte Ubl 3ce9370b35 Acyclic contract type: classes and object types that cannot lie on a cycle
`class C implements Acyclic`, `interface I extends Acyclic` and
`type T = Acyclic<{ ... }>` promise that no chain of references leads
from such an object back to itself. The check is the cycle analysis that
decides tracing, so a proven type carries no cycle-collector header. When
it does not hold, SC7007 shows the cycle: the path of fields, and why it
can close (a field assigned after construction, with the first such
write; an array, Map or Set; a function, dynamic or promise field; a
subclass sharing the layout). cycle-analysis.ts gains explainCycle over
the same graph with edge labels; computeTraced is unchanged.

Acyclic elsewhere is reported with SC7006. Docs, @scriptc/types,
corpus 4642, diagnostics snapshots and TypeScript baselines included.
2026-10-11 16:30:24 -07:00
Malte Ubl 5cc3babc73 Add the ProgramLifetime contract: classes whose instances live until exit skip reference counting and cycle collection
`class Node implements ProgramLifetime` (@scriptc/types, import type only, erased for Node) promises that instances of the class and of its subclasses are kept until the program exits. scriptc then creates them immortal: `new` stores rc = SIZE_MAX and allocates no collector header, the class's retain and release entry points are empty (so reference counting on every static type of the hierarchy folds away), and the cycle analysis treats the hierarchy as a leaf, which untraces types that only reached it. Immortal objects are already part of every RC, collector, weak-collection and publication contract (static literals, published graphs).

The promise only changes memory use; SC7007 refuses it where something else could observe it: on a class that is not the root of its hierarchy (including built-in bases), in library builds, and on classes whose instances can be published to other threads. SC7006 reports the marker outside a class's implements clause.

tsc-ts with nine roots marked (Node, NodeList, FlowNode, Symbol, Type, Signature, IndexInfo, SymbolLinks, NodeLinks): single-threaded wall -25.8% Excalidraw, -22.2% TypeORM, -25.9% self-check, -28.5% Sentry; peak RSS -6.5% to -16.5%; identical diagnostics.
2026-10-11 16:30:23 -07:00
Chris Tate fa11424e5f Prepare v0.2.9 2026-10-11 17:25:14 -05:00
Malte Ubl bb274adc5d Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	packages/compiler/test/ts7/baselines/order-parity.json
2026-10-11 13:27:39 -07:00
Malte Ubl 947c9bcf3f Contract types: explain throwing paths, bind only declared functions, docs and baselines
- NoThrow diagnostics name compiler-resolved Node errors (class and message)
  and explain parameters the frontend compiles as T | undefined because a
  caller passes a possibly missing value (for example xs[i]!), naming that
  call.
- Synthetic dynamic-class helpers (%dyn.*) carry the location of the code
  that first needed them; they are no longer bound to annotations there.
- Int32 hints only parenthesize where needed; the NoThrow hint no longer
  suggests try/catch, which does not discharge the contract.
- Diagnostics snapshots and TypeScript preflight/order baselines for the new
  fixtures.
- Docs: /docs/contracts and a limitations entry.
2026-10-11 12:24:27 -07:00