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 corpus program deliberately carries refused statements on untaken paths; the `// @deferred-fences: 9` header is the coverage sweep's exemption for such programs (9 failed statements across the speculative and final lowerings), so it still runs against Node in the differential oracle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
resolveInferredReturn turns a return statement into a runtime fence
through a Record<string, unknown> view with element writes
(`mutable["kind"] = ...`). The class method census treats a literal
element write as a possible write to every method of that name, so in the
native compiler every method named `kind` or `code` became a dynamic
callback: AstWireFile.kind, called for each AST node access, went through
a property bag and a method value.
Property writes go through the receiver check instead, and no class
instance is assignable to Record<string, unknown>, so those methods are
called directly again. Output of the compiler is unchanged.
T10 and T12 of the zero-cost compatibility plan, plus the maintainer
decisions:
- Programs that name Temporal type-check against TS 7's temporal lib
(added only for them) and lower to Node 24's answers: typeof is
"undefined", globalThis.Temporal is undefined, other uses throw
ReferenceError at the root read.
- node:v8 is importable; getHeapStatistics answers allocator-derived
figures in Node's shape; other members fence with the by-design reason.
vm's refusal says why.
- node:stream/web exports the web stream globals themselves.
- node:dns/promises and dns.promises: lookup and lookupService as
promises, in the link-gated scr_dns_promises.c unit.
- eval and the Function constructor throw Node's EvalError under
--disallow-code-generation-from-strings; the corpus harness runs the
Node oracle with that flag for `// @disallow-code-generation`.
- graceful-fs is served as node:fs.
Every new lowering replaces a refusal, and the new runtime code links only
when used, so other programs compile to identical bytes (zero-cost gate).
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>
The previous change dropped the diagnostics of a function-local class refused during a speculative whole-program type query, expecting the class's own declaration to report them. In JavaScript that declaration only defers them to a runtime fence, so two npm programs that the compile refused (stream-shims and node24-file-url-conversion, both SC1090) began to compile and diverged from Node at run time. The speculative query now leaves the refusal reported, as it was wherever such an analysis already caught the poison, and only stops the poison from escaping the compiler.
The JavaScript crash repro becomes a diagnostics fixture (local-class-type-query-js.js); the corpus program 6102 never crashed the base compiler and is removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The diagnostics snapshot for speculative-function-refusal.ts and the ts7 order-parity baselines for it and 6110-cjs-speculative-wrapper-fences.cjs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A zlib options object that reaches the runtime as a typed reference (a
cast object literal such as `{ level: 0 } as zlib.ZlibOptions`, which the
checked-dynamic options slot holds by reference) was not a plain
checked-dynamic object, so the options reader found no keys: every option
was ignored and out-of-range values were not reported. The sync, callback
and promisified one-shots and the stream constructors compressed with the
defaults instead.
scr_zlib_options_parse and scr_zlib_stream_new now read a typed reference
through its materialized view, as the blob and fetch option readers do, so
the options apply and invalid ones throw Node's ERR_OUT_OF_RANGE.
A refused statement in a JavaScript function body was dropped without a diagnostic or runtime fence when the body lowered inside a capture buffer whose owner kept the result. tryLowerExpression lowers the receiver of `(function () { ... }).call(this)` or `.apply(...)` and a computed class base that way: the refused statement (for example `console.log(root === module.exports)`) was missing from the kept function, its diagnostic was handed back to the enclosing statement, and that statement, having lowered cleanly, filed it as an informational runtime-fence entry. The program printed nothing for that statement.
lowerStmts now emits the statement's runtime fence inside a buffer as well (Lowerer.capturedRuntimeFence, the same message deferToRuntimeFence would give), leaving the diagnostics with the buffer's owner. The three JavaScript class initializer sites that skipped their fence under a buffer (static field, instance field, static initializer block) do the same. An owner that discards the candidate discards the fence with it, so every program that compiled before keeps byte-identical IR unless it contained such a dropped statement: all 3006 corpus programs produce the same IR as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The self-hosted compiler refuses a conditional spread of `tiers` over a
LowerResult that already declares the field, so assign it instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A shape union's arms all carry a collector header when one of them does.
The emitter applied that rule in one pass over the unions in module order,
so a header that a later union gave a shared arm did not reach the other
arms of an earlier union. With First = A | B and Second = B | C, where only
C is cyclic, B got a header through Second, First's trace helper then
called A's trace function, and A had none: the module failed LLVM
verification with "use of undefined value '@sc_rtrace_r0'".
The rule now repeats until no union adds a header. Corpus
5919-record-unions-shared-arms chains Third = D | A, First = A | B and
Second = B | C, so the requirement passes from Second through First to
Third.
Each local-time getter (getFullYear, getMonth, getDate, getHours, ...,
getTimezoneOffset) called localtime_r and walked the calendar for its
own field. The thread now keeps its last local conversion, keyed by the
instant and a timezone generation, so reading several local fields of
one Date converts it once. The UTC walk and the second computation use
integer division instead of floor.
Writing or deleting process.env.TZ calls tzset and starts a new
generation, so later local-time reads use the new zone, as in Node.
Before, the zone the process started with stayed in effect.
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.
Class dynamic dispatch decides whether a class family keeps a fixed
field layout from the property names a delete can remove. It cached that
set with ??=, but the scan returns null when the program reflects on
properties, so a program that does recomputed it, walking every source
file, for each class in every dispatch wave. Only an undefined value now
means the set has not been computed.
npm-static re-export pruning read and parsed a package's package.json
for every file whose purity it checked, and for every package boundary
an import crossed. Each plan now parses each package.json once.
Output is unchanged. three.js nodes lowering takes 6 s less and an
Effect fixture's frontend load 4 s less.
Node runs runNextTicks after each timer and each immediate callback, which
reports the unhandled rejections the callback left before the next one runs.
The event loop now leaves the timer phase when a callback leaves the
rejection ledger non-empty, the check phase waits for that report, and the
check phase reports the ledger after each immediate's checkpoint.
When several timers expired in the same turn, a later timer ran before an
earlier timer's rejection was reported. On macOS the 2 ms and 3 ms timers in
5809-process-exit-and-rejections.cjs expire together, so its uncaught
'thrown string' was printed before the TypeError rejection.
5996-rejections-between-macrotasks.cjs makes five timers expire in the same
turn and checks the order across three immediates.
The gate read an empty symbol list when nm could not start, was killed by
a signal, or exited with a non-zero status, so the dynamic-tier symbol
check and the executable comparison passed without any symbols. nmOutput
now throws with the binary, the reason and nm's stderr.
Rerun scripts/ci-corpus-costs.mjs over the 120 green Linux corpus shard
logs (plain and san, 20 shards each) of main CI runs 39142848734,
39142619508 and 39142079655 (307387c8e, 18c50b55d, b85dd44cd). Their
Linux lanes were all green; only macOS jobs were still queued.
This measures the programs added since the previous refresh, including
5770-5773, 5960-5962, 5973, 6041-6043, the CommonJS require programs
6140-6145 and 5023/5024. Coverage of current main's corpus goes from
2992/3012 (0.9934) to 3011/3012 (0.9997); the one unmeasured program,
scratch-string-slices.ts, landed after those runs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>