0.4.0
Breaking changes
- tsc-ts is the default TypeScript 7 checker on Linux and macOS. scriptc installs it with the compiler (
tsc-ts0.0.5 and its platform package for the host). Programs get the same diagnostics and generated code as with tsgo, and compiling takes less checker memory.SCRIPTC_CHECKER=tsgoselects tsgo, which stays the default on Windows. A build cache entry made with one checker isn't reused with the other. --npm-static=auto, the default, compiles more packages: packages typed by their DefinitelyTyped twin (@types/<name>), and untyped dependencies that another package's JavaScript imports. A program whose dependencies were refused before can now compile them, and a twin whose declarations disagree with the package's JavaScript fails the build at the use. Use--npm-static <pkg,…>to name the packages to compile.- Program type errors are reported as type errors instead of as refusals of the npm package that contains them.
Highlights
- WebAssembly: builds translate every WebAssembly module whose bytes they can see into native code, and
WebAssembly.compile,instantiate,validate,new WebAssembly.Moduleandnew WebAssembly.Instancerun them. There is no interpreter.WebAssembly.Memory,TableandGlobal,Module.imports,Module.exportsandModule.customSections, and function references from tables are supported, and modules can be sent to workers.scriptc coveragelists the modules a program loads, with--wasm <file.wasm>for modules loaded from paths the sources don't spell out. - Async functions that suspend only at their
awaits run as stackless coroutines instead of on fibers with their own stack, so a suspended call keeps only the values live across its awaits. - Discriminated unions of records are the record pointer itself, with no box around each value.
- The dynamic tier computes with NaN-boxed values: numbers, booleans,
undefinedandnullbetween operators no longer allocate.scriptc coverage --explain-dynamiclists the functions that run in the dynamic tier and why, and--tier=static-onlykeeps a program fully static. - npm packages: esbuild's bundled CommonJS chunks, CommonJS cycles and lazily initialized ES modules compile statically, as do classic CommonJS packages (late and JSON
requires, require cycles), class hierarchies across a package's modules, and the packages unblocked by type-only imports,@typespackages,punycodeandconstants. chalk 5 and the jose root entry compile.
Features
@scriptc/experimentaladdsThreadSlots, one value per key and thread on shared objects, read without a lock.node:testaddsmock.timers,getTestContext,t.assert.snapshotandt.assert.fileSnapshot, theTestContextvaluesfilePath,attempt,passed,workerIdandtags, module-levelbeforeandafterhooks, theSuiteContextand hook contexts, and unnamedtestanddescribecalls. A timed-out test cancels its running subtests.node:worker_threadsaddsBroadcastChannel,setEnvironmentData/getEnvironmentData,receiveMessageOnPort,markAsUntransferable,markAsUncloneable,threadName,resourceLimits.stackSizeMb, thestdout/stderr/stdinoptions and streams, andworker[Symbol.asyncDispose].node:netaddsSocketAddressandBlockList, andnet.connectresolves host names.node:httppools keep-alive sockets inAgents, usesglobalAgentfor default requests, readshttp.requestoptions at run time, and speaks HTTP over Unix domain sockets.fetchtunnels throughHTTP_PROXY/HTTPS_PROXYwithCONNECT.DisposableStack,Float16Array,Error.isError,Promise.tryand the regular expressionvflag are supported.- Iterator helpers run on generators,
MapandSetiterators, string and typed array iterators,Iterator.fromand untyped iterators. Object.groupByandMap.groupBygroup Sets, Maps and generators.v8,stream/web,dns/promises,EvalErrorandgraceful-fsare available, andTemporalis reported as absent, as in Node 24.util.promisifyworks over the crypto callback functions, dns lookups,child_process.exec's callback forms and callback-style functions.events.oncetakes anAbortSignaland works over streams.AsyncLocalStoragestores carry into timer, immediate,process.nextTickand microtask callbacks.- JavaScript classes compile like TypeScript classes when their layout or JSDoc types allow it.
- Classes that extend
EventEmitteror a stream class can be used as values, and so canEventEmitter, the stream classes and the error classes themselves. Constructor functions can inherit from them. - Class instances can be frozen and their fields redefined.
- Method overrides may differ from the method they override in parameter and result types, as long as each value converts.
- Library profiles add the
cstringclass. - An experimental young-object nursery for compiled classes and records is available at compile time with
SCRIPTC_YOUNG_NURSERY=1.
Performance
- Dense arrays have head room, so
shift,splice(0, n)andunshiftruns cost amortized O(1), andpopof a packed array is inline. - Index loops over arrays and typed arrays are versioned on one bounds guard, with stable lengths proven and typed-array memory tagged for alias analysis.
- Retain and release pairs are removed through private-array precision and last-use moves, borrowed string slices go into stack buffers, and records, tuples and spread updates stay in frame storage.
- SHA-384 and SHA-512 use AVX2, AVX-512VL or the arm64 SHA-512 instructions, and MD5's block function is unrolled.
- String character tests, optional-string
switches,String.fromCharCodeand long-stringlengthare faster, andBuffer.writewidens ASCII to UTF-16 sixteen bytes per step. - The cycle collector walks dead cycles once, frees large dead cycle sets in address order and no longer creates self-capture cycles on the release fast path.
- Workers return their memory while the event loop waits and when they finish, and default-region memory is committed as it is used.
- Lifetime regions carry across
await, and freed region chunks are reused. - Large closure environments compile in linear time, and two frontend scans no longer repeat.
- Programs keep stack frames only when they can read
stack. Before, a computed-key read on a dynamic value kept frames in every function; tsc-ts's own check is back to 0.3.6's speed. - The child-process runtime unit links only into programs that spawn.
Fixes
- Node 24 parity:
util.format,util.typesandutil.inspect,URLSearchParams,querystring(null-prototype results),string_decoder,os,eventsandtimers/promisesmatch Node 24. Class instances, iterators, iterator helper objects and holes in arrays print as Node prints them, and%d/%iformat dynamic arguments as Node does. - Silent wrong output is fixed for object identity,
Object.prototypevalues,Date.parse(V8's date grammar), stored builtins, constructor returns,arr && arr[0], ES5 class names, builtin function values, uninitializedletwrites, module-exportthisand1 ** Infinity. - Strings compare in UTF-16 code-unit order.
- Dates format with Node's local time zone names, convert to local time once for their local getters, and follow
TZchanges.Date.prototype.toJSONgivesnullfor invalid dates. - Errors: thrown Maps, Sets, typed arrays, functions and arrays keep their identity. Errors list their own name where they were created, errors held as
anyhave their ownstackaccessor and convert withError.prototype.toString, and errors that cross into dynamic code carry Node's error properties. matchAllrows andexecresults haveindex,inputandgroups, and named groups keep their null prototype through optional chains.- Unhandled rejections are reported after each timer and immediate callback, and async generator completions settle on Node's microtask turns.
- Missing
Recordand index-signature keys read asundefined, and generic functions that read a missing element returnundefined. - Sockets:
'data'listeners get strings aftersetEncoding, socket and stream chunks are Buffers, and an idle pooled http socket that receives data is destroyed. - Diagnostic code frames window long source lines.
- npm crashes, internal errors and false TDZ errors found while compiling popular packages are fixed.