The fixture's launch() helper calls run().then, which used to be the
first statement these programs fenced at (SC1090). It compiles since
#1503, so node24-web-stream-pipe-abort and
node24-web-stream-readable-lifecycle now stop at 'new ReadableStream'
and node24-web-stream-tee at 'ReadableStream.tee', which have no
lowering (SC2020).
Node's promisify copies the original's own property descriptors and
prototype onto the wrapper and consults util.promisify.custom. The
runtime wrapper now copies name and length and refuses, with SC2020 where
util.promisify runs, an original with any other own property, instead of
returning a wrapper that lacks them. The node24-util-adapters npm case
now gets past its promisify scenarios and stops at an unrelated deferred
Object.create refusal; its known state records that.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Node passes write and end callbacks an error argument (null on success),
but the native callbacks receive none, so an inline callback that names
the parameter read undefined. It now refuses where it is written. The
stream-shims npm case compiles now that stream subclasses are values;
its remaining scenarios are deferred refusals, so it is recorded as one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The undici cases compile the built-in undici implementation's module
graph; a sanitized build of it on a CI runner outlasted the default
120 s per case.
cjs-lexer-invisible and hoisted-workspace compiled only once their
untyped dependencies were selected; both now match Node in both lanes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fs-shims now gets past Buffer.isBuffer on a Uint8Array (fszoo/index.js:35),
which this branch lowers; its first deferred refusal is the existing
SC1101 for a closure passed into an unknown slot (fszoo/index.js:44), so
the expectation records SC1101.
The branch's new corpus programs (1112 and 6200 to 6210) get per-program
cost files in tests/harness/corpus-costs, taken from the differential and
llvm-differential case durations in this branch's Linux CI shards.
scr_dyn_invoke.c links into libraries that use dynamic calls, and its stored
timer functions call scr_set_timeout_handle, scr_set_interval,
scr_clear_interval, scr_set_immediate, scr_clear_immediate, scr_next_tick
and scr_queue_microtask_dyn, which live in scr_async.c. Libraries never link
scr_async.c (a library that schedules timers is refused at SC4005), so their
host links failed with undefined symbols. Under SCR_LIB the calls that
schedule are left out, and a call through a stored timer function throws the
SC4005 event loop error. Executables compile the same code as before.
- 6236-builtin-function-values.cjs counts the interval's runs apart from the
order of the other callbacks and reports once the interval has stopped, so
a slow machine prints the same line as Node.
- node24-util-types: Function now reads as a value, so the fixture's first
refusal is the SC1090 for extending Promise instead of the SC2009 for the
FunctionConstructor value.
Resolve the dns/promises libCalls against main's util.promisify(dns.lookup)
forms: main's dns.lookupPromise/scr_dns_lookup_promise keep their
promisify semantics, and node:dns/promises moves to dns.promisesLookup /
scr_dns_promises_lookup in scr_dns_promises.c. Generated compatibility
files are main's, regenerated with pnpm manifest and pnpm node-compat.
The npm harness's web-stream fixtures now compile and defer their
refusals, and node24-util-types defers at its Promise subclass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The npm compatibility probes ranked these CommonJS forms among the top blockers. They now compile with Node's semantics inside the static CommonJS model, where exports stay module globals or alias plumbing to declarations. Every remaining form keeps a refusal that names the construct.
- Inline require() of program modules (cjs-inline-require.ts). `require("./x").f`, `.f(...)` and `new (require("./x").C)()` over a table module run the module's run-once %init at the call's position, then resolve the member like a binding does. `require("./x")` as a value over a single-value module is that value (`require("debug")("ns")`, table entries, construction). Inline requires are preflight module edges. An edge in a function body is lazy: it orders the dependency after the requiring module and does not close initialization cycles. Other require() calls name their construct instead of reporting an unlowerable 'Require' value. A package that nothing installed resolves throws MODULE_NOT_FOUND.
- module.exports = require("./y") or a require binding (re-export), = TypeError (a builtin global), and = any computed value (`a || b`, ternary, `new X()`). Chained `exports.a = exports.b = v` evaluates v once. Export members assigned in value position (`const src = exports.src = []`) or inside functions write the export global. A fresh `exports = module.exports = {}` reset at the top of a module is a no-op. Any other rebinding of `exports` is refused by name.
- A module's own exports object (cjs-exports-object.ts). Identity comparisons, typeof and truthiness of `exports` / `module.exports` use the object that top-level `this` already represents, while the module keeps its original exports. This covers the `root === module.exports` statement that used to vanish from `.call(this)` wrappers. `exports.f(x)` calls the member's export global when no assigned value can read `this`. Other value uses are refused by name, including in CommonJS files where the message used to say "ES module".
- tsc interop (cjs-tsc-interop.ts). `const x_1 = __importDefault(require(...))` and `__importStar(...)` are require bindings, stamped and unstamped. The helper declarations lower to nothing once every call is such a binding.
- Export tables: method entries compile, and `...require("./x")` spread entries now evaluate x at their place. Before, the module was never initialized.
- TypeScript reads of members a JavaScript module attached to an exported function go through the function's own property table.
- Nested require destructuring of program modules, `const { codes: { E } } = require("./errors")`, destructures the named export at the require (SC1012). `const { A } = ns` over a module binding snapshots the export.
The capture-buffer fence tests merged from opt/cjs-exports-value used `root === module.exports`, which now compiles. They use eval() to keep testing the fence.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the local-class refusal reported again, both npm fixtures fail to compile with SC1090 as they did before #1303; restore their build expectations. The deleted corpus program 6102 also leaves the measured cost table.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both fixtures declare a function-local class whose base has no static
lowering (`class FileURL extends URL {}`, `class Counter extends
Readable`). The SC1090 for it used to come from the whole-program type
queries, which collected the class outside any statement, so the build
failed. Those queries now keep a refused local class out of their
results and drop its diagnostics; the class declaration reports the
refusal when it lowers, and in a JavaScript source a refused statement
becomes a runtime fence. Both programs therefore compile and throw the
fence when they reach a construct without a lowering, like the other
fixtures listed with a run refusal.
With untyped Buffer.concat lists and typeof on builtin module exports supported, the fixture runs to completion and matches Node, so its expected deferred SC2020 refusal is removed.
Its package puts a cyclic object (cycle.self = cycle) in an array literal
with other values. The literal used to convert that checked-dynamic
object into a recursive record type and crashed; it now builds as a
checked-dynamic array that holds the object itself, so the program runs
as under Node and is no longer a known divergence.
The npm case fixtures lost their only native test with the native-only
compilation change. tests/harness/npm.test.ts runs every case again with the
default static npm compile and compares it with Node. A KNOWN table records
the cases the compile refuses (with the diagnostic code), the cases whose
run reaches a deferred refusal (the code in the program's output), and the
two that still diverge, which run as expected failures. The suite joins the
case-sharded CI corpus files.
Fixes from the run:
- A package imported only by subpath (`pkg/env.js` from a package with no
"main", "exports" or index file) was refused as having no runtime entry.
Eligibility now resolves the imported specifier when the root has none.
- diagnostics_channel: a throwing subscriber stopped publish, and a
throwing bindStore transform stopped runStores. Node runs the remaining
subscribers, skips that store, and reports each error as uncaught on a
next tick; the runtime now does the same.
- A '#' import that the package's "imports" field maps to another package
failed at run time with Node's "not defined" error, which Node does not
raise. It is now a compile-time SC1010 refusal.
- An uncaught runtime refusal whose code is an SC code now names the code.
- Mapping a type in the optional array-element analysis could lower an
unsupported local class and let its PoisonError escape as a compiler
crash; the analysis now treats that element ABI as unknown, so the
program fails with the recorded diagnostic.
- A lexical module binding initialized from an unchecked array element
holding a function failed validation (SC9001): its widened storage was a
union, which a TDZ guard cannot hold. Such bindings now keep checked-value
storage and their guard.
- A dynamically reached ArrayBuffer had no constructor property.
- Enforce oxlint and oxfmt for owned JavaScript and TypeScript with independent CI checks.
- Preserve compiler import boundaries and protected fixtures while cleaning up lint findings.
- Standardize source formatting and validate import, fixture, and embedded-source protections.
* Expand Node 24 filesystem descriptor and FileHandle support
* Preserve filesystem options getter evaluation and record fixture baselines
* Normalize the known Linux fiber warning in npm stderr comparisons
- Make DNS promises imports load with the expected exports and explicit query errors.
- Resolve CommonJS directory requires used during Redis initialization.
- Record the missing TypeScript order baselines required by the full gate.
Fixes#434
Co-authored-by: Artem Gurtovoi <1233869+temich@users.noreply.github.com>
* feat: support wasm32-wasi as a production target
- Add production LLVM WASI codegen with a 32-bit ABI, coroutines, and dynamic modules
- Integrate WASI builds and execution into the CLI with capability diagnostics
- Add differential coverage and document the fourth production target
Co-authored-by: Albert <57402359+bulatovv@users.noreply.github.com>
* fix: address wasm target review findings
* fix WASI guest paths and fetch alias detection
* fix WASI async bridge and fetch detection
---------
Co-authored-by: Albert <57402359+bulatovv@users.noreply.github.com>
- ci.yml runs test (plain|san, 1..3/3) on macos-15; an aggregate job keeps the old "test" check name for anything pinned to it
- each job runs vitest twice: --shard=i/3 over everything but the corpus lanes, then the four corpus lanes with only their case slice — a file lands in exactly one --shard slice, so mixing the axes would silently drop cases
- tests/harness/shard.ts: SCRIPTC_TEST_SHARD="i/n" slices case lists by sha1(name) mod n — stable across corpus growth, every case in exactly one shard, unset means everything
- differential, llvm-differential, npm, and server harnesses slice through it; the llvm tier-floor assertion checks only this shard's floor programs
- shard.test.ts pins the partition contract (union exact, disjoint, key-stable, env-driven default) and stays green with the job-wide env set