Its merge of main resolved scr_cycle.c and test_cycle.c identically;
this side's newer main and the 5985 renumbering stand.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A request that took a socket from a keepAlive agent, either queued for a
freed socket or taking a free one, parsed its response with the parser
of the request that used the socket before, and with that request's
maxHeaderSize. A smaller limit was not enforced, and a larger or default
limit was cut down to the earlier one. The request now keeps its limit
(0 for the default) and applies it to the pooled parser when it takes
the socket, before any response bytes are parsed.
Corpus 5594 covers both handoffs with smaller, larger and default limits.
Corpus 6110 has three statements with no static lowering, and its
@deferred-fences directive is 9 because coverage counts each lowering of a
wrapper body: the .call and .apply wrapper bodies are each lowered four
times. The program's header now says so. The commit also adds the
program's corpus-costs entries, which shard balancing reads.
`s.match(re) || []` contextually types the empty array by the tuple-like
RegExpMatchArray, so typescript-go builds an empty tuple target and
clones it as an array literal. The clone keeps ObjectFlagsTuple on
TypeReference data, and the API's newTypeResponse panics (interface
conversion to *TupleType) whenever it serializes the clone, for example
as a member of `RegExpMatchArray | []`. Whole-program analyses asked for
such union members first, so every program containing the pattern
(moment.js, or a two-line TypeScript file) failed at 1:1 with SC0004.
A union whose members typescript-go panics to serialize is now
unmappable at the top of mapType, the any-array probe answers false for
it, and the panic is remembered per type instead of re-requested.
Queries that still need the members keep the source-anchored SC0004 on
their own statement (a runtime fence in JavaScript). Other checker
panics are unchanged. The panic itself is an upstream bug in
internal/api/proto.go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A reference to a later function declaration in the same function scope
lowers that declaration on the spot (predeclareForwardFnDecl), and the
result is kept. When the reference sat inside a speculative attempt
(tryLowerExpression's temporary diagnostic sink, here the native
function assignment in bignumber.js's `var P = BigNumber.prototype =
{...}`), the hoisted body lowered under that sink: its failing JavaScript
statements were dropped instead of becoming runtime fences. bignumber's
`isBigNumber` lost its only `return`, so every program using the package
aborted at load with SC9002 "a non-void function completed without
returning", and its constructor silently lost its instanceof check.
Lower the hoisted declaration without the probe's sink, as eager generic
instances already do. A declaration that fails as a whole is not kept,
so its diagnostics go back to the probe.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The runtime-optional analysis widens a parameter or binding that can
observe undefined with an undefined arm. For a Date it interned the
union `Date | undefined`, which is not a valid union (Date is not a
union arm kind), and the whole program failed IR validation with SC9001
"union uN: arm 0 is date" (morgan's date token and clfdate).
Like generators, a Date keeps its type: the canonical undefined-arm
helper already refuses Date, and a site that would store undefined into
the slot keeps its own diagnostic.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`fs.readFileSync(file, { encoding })` and `fs.promises.readFile` read
the encoding field straight off the lowered options literal. When the
encoding value is checked-dynamic (dotenv's `t = e.encoding`), the
literal lowers to a dynamic object, and the record field read failed IR
validation with SC9001 "recordGet receiver: expected record, got dyn".
Check such a literal into the `{ encoding: string }` record the checker
describes before reading the field.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A keyed read whose checker type is a record but whose storage is
`record | null` (iconv-lite's `module.exports.encodings = null`, filled
on first use and read as `encodings[enc]`) built a recordKeyGet on the
union and failed IR validation with SC9001.
The optional-receiver guard that keyed reads already use for
`record | undefined` now also takes a null arm for string and number
keys: the receiver and key evaluate once, a null receiver throws Node's
"Cannot read properties of null (reading 'k')", and a present one reads
the record. Other keys keep their checked-dynamic read, and keyed writes
are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts with #1286's merged form and the death rule (74702ac4b):
- scr_cycle.c: keep the death rule's per-thread fields and drop the
running buffered total this branch removed (the slow path sums the
buffers); scheduling decisions route bypassed appended candidates and
then note the live count's fall.
- test_cycle.c: keep both new checks (inline buffering, death brings a
full pass).
- The self-capture corpus program moves from 5990 to 5985 (5990 is now
5990-worker-uncloneable.mjs), with its order baseline.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scriptc's resolver and tsgo must answer one runtime file for every
opted-in npm edge; four disagreements left the file outside tsgo's
program (SC2013 "did not join the type-checked program") for express,
axios, body-parser, execa, fast-glob, globby, knex, uuid and tldts:
- uuid: the node-condition hoist re-added the inner "types" key after
the claims were deleted; tsgo then took the browser build. Delete the
claims after the hoist.
- tldts: tsgo's TypeScript-first lookup took the shipped root index.ts
over "main". The fs shadow hides installed TypeScript sources of
opted-in packages that have no same-stem runtime JavaScript.
- express: tsgo redirected same-version duplicate installs to one copy,
either dropping a copy or merging two Node module instances into one.
The shadow serves opted-in package.json files without "version".
- deep chains (get-intrinsic, dunder-proto, run-parallel, reusify,
supports-color): maxNodeModuleJsDepth charges every node_modules hop.
The program-root fixpoint also roots opted-in bare edges' runtime
files that the program is missing.
All changes are gated on --npm-static being active.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`var nextTick = typeof setImmediate === "function" ? setImmediate :
setTimeout` (bcryptjs) and `cond ? setImmediate : process.nextTick`
stored the builtin as an identity token string, so typeof answered
"string" and calling it threw "nextTick is not a function". The JavaScript
identifier, `globalThis.X` and destructuring spellings of setTimeout,
setInterval, setImmediate, clearTimeout, clearInterval, clearImmediate and
queueMicrotask, and a stored process.nextTick, now read one interned
runtime function per name. Conditional, logical and assigned values carry
it like any function: typeof is "function", identity holds across
spellings, and calls validate the callback (ERR_INVALID_ARG_TYPE), coerce
the delay, pass the extra arguments and return the same numeric handles
the direct calls return, which the stored clear functions accept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`const { hasOwnProperty } = Object.prototype`, `Object.prototype.constructor`
and `hasOwnProperty.call(Object.prototype, "constructor")` hit the runtime
"Object.prototype reflection and mutation" fence (acorn, ini,
safe-stable-stringify and qs read the prototype this way). Reads of the
prototype's constructor and shared methods now answer the same interned
values the inherited reads answer, own-property checks see its twelve own
members (none enumerable), and Object.prototype.toString.call(error)
answers "[object Error]" instead of "[object Object]". Mutation and the
remaining reflection (isPrototypeOf, __proto__, accessors) stay fenced.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fast-deep-equal and every isPlainObject idiom compare `o.constructor ===
Object` and `o.valueOf === Object.prototype.valueOf`. Natively a dynamic
read of an inherited Object.prototype member answered undefined and the
JavaScript identifier `Object` was a string identity token, so
equal({a: 1}, {a: 1}) was false with no diagnostic.
The builtin constructors Object, Function, Date, RegExp, Map, Set,
Promise, WeakMap and WeakSet now read as interned function values (in
TypeScript too, where they were refused), and dynamic values answer
`.constructor` with the same functions: plain objects (including
Object.create chains), arrays, functions, class instances and the native
Date/RegExp/Map/Set/WeakMap/WeakSet/Promise values. A member no nearer
prototype defines falls back to the interned Object.prototype method
`Object.prototype.<name>` reads (valueOf, toString, hasOwnProperty,
propertyIsEnumerable), respecting the types that define their own
toString or valueOf. Typed records and class instances read these
members through their dynamic view instead of hitting the stdlib fence.
`instanceof` accepts the constructors, and `Object(v)` / `new Object()`
work through a stored value; calling the other constructors through one
stays fenced.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The multi-argument Date constructor was refused (SC2020), which blocked
date-fns and consumer code that builds dates from calendar fields. Typed
callers now lower to a seven-f64 runtime call (omitted trailing fields
complete with the spec's defaults) and JavaScript callers pass their
arguments through ToNumber in order. The runtime mirrors V8: MakeDay
bounds the untruncated year and month, years 0-99 map to 1900-1999,
fields roll over, and the local time value converts to UTC in the host
zone with the same UTC(t) the date parser uses, then TimeClip. Spread
arguments stay fenced.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Date.parse and new Date(string) answered NaN natively for every form
outside ISO 8601 with an explicit offset and the X509 certificate shape,
so RFC 1123 HTTP dates ("Mon, 01 Jan 2024 00:00:00 GMT") never parsed and
the fresh/express/send conditional GET never matched. The runtime now
falls back to a port of V8's DateParser (the ES5 date-time format, then
the Safari-compatible legacy grammar: weekday and month names, RFC 2822
offsets, zone abbreviations, AM/PM, parenthesized comments, slashes) for
exactly the strings the bounded grammars reject, so the timestamps they
accept cost nothing more. Zone-less dates are local time, converted with
the spec's UTC(t) over the host zone (DST gaps read with the offset before
the transition, overlaps answer the earlier instant).
With native parsing matching Node for every input, the SC6005 literal
warning has nothing left to report and is retired rather than extended to
non-literal inputs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The runtime ABI test reads every @scr_* spelling in the backend sources
as a symbol the backend can emit; the gate's regex spelled a truncated
@scr_weak_ prefix. Test the two declarations by their full names.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
A full SCRIPTC_UPDATE_BASELINES=1 re-record of order-parity.test.ts changed no existing baseline; these are the seven new fixtures (6150-6156). 6150's order places late.js after main.js, the lazy inline-require edge.
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>
`const E = EventEmitter`, `const M = Map`, `const T = TypeError` and
`const R = Readable` stopped at SC2020, and so did `typeof EventEmitter`,
`Readable.name`, `Map.name`, `Error.name` and `===` between builtin
classes. The zlib class alias resolver now covers the error classes,
EventEmitter, the node:stream classes and Map/Set: a const binding of one
(an alias of an alias, or an export used through a named or namespace
import) constructs, extends and tests instanceof like the direct name,
and typeof, .name and === fold for aliases and direct names.
In TypeScript files the alias owns no runtime slot and other value uses
report SC1090 at the use. In JavaScript files a copy of a name or of a
globalThis property keeps its slot, which holds the same value as the
name it copies; builtin module members (`zlib.Gzip`) own none, as before.
main now has #1286 and later collector changes. Resolved in scr_cycle.c:
the scheduled collection point collects the nursery, then notes the
live-count fall (death rule). Semantic fixes for the new main code:
a full pass's markGray no longer overwrites a young object's `buf` (its
nursery index) with the component number, and a nursery collection
refreshes the death rule's live reading at its end so the young garbage
it frees does not count as deaths outside passes. Formats the runtime
pack matrix test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A package-anchored preflight diagnostic that makes the build drop an npm package was reported only at the consumer's import, as `SC2013 cannot compile npm package 'ws' statically: SC1012: …`, with the package file and line lost. The refusal reason now carries them (`SC1012 at ws/lib/websocket.js:30: …`), in the SC2013 diagnostic and in the coverage report's package status. This is how the SC1012 construct behind ws, readable-stream, through2, socket.io and fastify was identified (nested require patterns, and a rest element in fastify), and how openai's SC1013 is located (`openai/internal/auth/x509-transport-state.mjs:2`).
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>
`b[i] = v` lowered to bytesSet whenever the checker's flow type of `b`
was a typed array, even when the binding's storage was wider. A hoisted
JavaScript `var` holds `bytes | undefined`, so the plain
`var dst = Buffer.alloc(n); dst[i] = x` (ecdsa-sig-formatter, dotenv)
and a field assigned after construction (@noble/hashes' HashMD buffer)
failed IR validation with SC9001 "bytesSet on non-bytes union".
For `bytes | undefined` storage with a number index, evaluate the
receiver, index and value in order, then throw Node's TypeError for an
undefined receiver or take the typed store. Any other storage takes the
checked-dynamic store, which applies the value the receiver holds; a type
with no checked-dynamic form is refused with a named diagnostic.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A reflected JavaScript class method lowers its lambda the first time its
value is read, and caches the closure only after the body lowered. A
method whose own body reads the method as a value, like i18next's
`instance.createInstance = I18n.createInstance`, reentered the lowering
for the same method until the compiler overflowed its stack.
Record the method while its lambda lowers; lowerLambda names the closure
it will produce, and a read of the method inside its own body takes that
closure, so every read sees the same function. When the body later
changes the closure (its type is settled by an inferred return, or it
captures), the self read is refused with a named diagnostic instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A top-level `let x;` in a JavaScript module holds a checked dynamic value
that the module %init fills with undefined at entry. When the module's
early-running code (a published function, a function declaration called
above the binding) can reach the binding, it also gets an initialization
flag, and every write before the flag is set is TDZ-checked. The entry
fill was rewritten like a source write, so the module threw "Cannot
access 'x' before initialization" before its first statement ran. That
broke json5, cliui and cosmiconfig on load.
Mark the fill as initializing when the global has a flag: it is storage
setup, not the source write, so it neither runs the check nor sets the
flag. Accesses that really happen before the declaration still throw.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep both the entry module's DEP0040 link warning and #1303's CommonJS
top-level this object in the module init header.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
React Flight's production server never runs its V8 structured-stack parser
(ReactFlightStackConfigV8): every use is behind __DEV__. Builds compiled from
its sources keep that code behind `throw new Error('... should never be
called in production mode')` stubs, so scriptc lowered it, failed on
Error.prepareStackTrace, and a dead `.stack` read turned on stack-trace mode
(a frame push in every function) for the whole program.
- Statements after return/throw/break/continue in a function body are not
lowered. Declarations keep their hoisting through the existing forward
machinery (later function declarations, `var` reads undefined, `let`/
`const` TDZ); class, enum, module, import/export and generic function
declarations still lower. Functions referenced only from such code are
unreached and dead-stripped.
- Stack-trace mode requires a stack read reachable through live code
(observesStacks).
- Synchronous functions in executables push and pop their source frame
inline instead of calling scr_stack_enter/leave.
- Functions that only perform operations which never create or throw an
Error, and only call such functions, keep no frame (captureFreeFunctions):
no capture can include them.
Error.prepareStackTrace and CallSite stay refused: only development Flight
runs them. Good code is byte-identical (zero-cost gate: bench and
self-hosted compiler IR, LLVM and executables).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Match results record their metadata lazily. The results of one exec or
matchAll call share a source (the subject and the regex), and each
result keeps its start index. index, input and a null-prototype groups
object are built when a result is converted to a dynamic value; .index
and .input on a match slice read the source directly.
matchAll rows are allocated inline, like exec results. A drain whose
rows are read only through their elements, .length, the .groups
projection and the companion index uses matchAllCaptures or
matchAllCapturesInto, whose rows carry no metadata.
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>