Commit Graph
6750 Commits
Author SHA1 Message Date
Malte UblandClaude Opus 5.5 f6f63bf0fb Merge the pushed opt/gc-closure-cycles (474012f04) into the local merge
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>
2026-10-18 14:40:34 -07:00
Malte UblandClaude Opus 5.5 14e599ecda Merge origin/main into opt/builtins-t10-t12
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 14:40:30 -07:00
Chris Tate a1453ccbbf Merge main 2026-10-18 16:38:07 -05:00
Chris Tate 82732a75bd Merge main 2026-10-18 16:32:59 -05:00
Chris Tate d0182e59c8 Merge main 2026-10-18 16:28:52 -05:00
Chris Tate f5eb459888 Unblock common npm packages: type-only imports, @types packages, punycode and constants (#1285) 2026-10-18 16:25:22 -05:00
Chris Tate db0066c542 Record corpus costs for 6110 and explain its deferred-fence count (#1328) 2026-10-18 16:13:03 -05:00
Chris Tate afef6f09f5 Apply each request's maxHeaderSize to a pooled socket's parser
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.
2026-10-18 16:12:14 -05:00
Chris Tate 66027d850b Explain 6110's deferred-fence count and record its corpus costs
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.
2026-10-18 15:53:37 -05:00
Chris Tate 474012f04d Merge main 2026-10-18 15:51:50 -05:00
Malte UblandClaude Opus 5.5 beddc5f94a Keep typescript-go's tuple-literal panic with the statements that ask
`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>
2026-10-18 13:51:44 -07:00
Malte UblandClaude Opus 5.5 92310a68fc Keep statement fences in functions hoisted during a speculative lowering
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>
2026-10-18 13:51:44 -07:00
Malte UblandClaude Opus 5.5 3b9272e8f8 Keep Date slots out of runtime-optional undefined widening
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>
2026-10-18 13:51:44 -07:00
Malte UblandClaude Opus 5.5 74646b783f Check a dynamic { encoding } option into its record for encoded reads
`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>
2026-10-18 13:51:43 -07:00
Malte UblandClaude Opus 5.5 21ae43bd88 Guard keyed reads of a null-initialized record table
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>
2026-10-18 13:51:43 -07:00
Malte UblandClaude Opus 5.5 886ea7009c Merge origin/main into opt/gc-closure-cycles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:49:20 -07:00
Malte UblandClaude Opus 5.5 98d4611ef6 Merge origin/main into opt/gc-closure-cycles
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>
2026-10-18 13:49:20 -07:00
Chris Tate ea7bcd9846 Resolve builtin classes through const aliases (#1327) 2026-10-18 15:42:15 -05:00
Malte UblandClaude Opus 5.5 e90c77d36a Make selected npm packages join the type-checked program
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>
2026-10-18 13:40:18 -07:00
Malte UblandClaude Opus 5.5 acfdc7fe13 Store builtin timer functions as real function values in JavaScript
`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>
2026-10-18 13:34:58 -07:00
Malte UblandClaude Opus 5.5 9fab4348d3 Read Object.prototype's own members as values
`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>
2026-10-18 13:34:57 -07:00
Malte UblandClaude Opus 5.5 1144e3cea4 Make plain-object constructor and Object.prototype method identity exact
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>
2026-10-18 13:34:57 -07:00
Malte UblandClaude Opus 5.5 40f15eb4b3 Lower new Date(year, monthIndex, ...) as local time
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>
2026-10-18 13:34:56 -07:00
Malte UblandClaude Opus 5.5 5a342ad1a5 Parse date strings with V8's grammar when the bounded parser rejects them
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>
2026-10-18 13:34:55 -07:00
Malte UblandClaude Opus 5.5 87b85d5b28 Name the weak collection constructors whole in the dispose gate
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>
2026-10-18 13:34:43 -07:00
Malte UblandClaude Opus 5.5 a2c4f584e1 Merge the branch's own main merge (6ea39a9c2) into opt/builtins-t10-t12
Keeps this branch's resolution (newer main), adds the recorded corpus
costs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:33:19 -07:00
Malte UblandClaude Opus 5.5 e3056b02f1 Merge origin/main into opt/builtins-t10-t12
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>
2026-10-18 13:32:40 -07:00
Malte Ubl 0620e30501 Merge origin/main into opt/tier-s1-leaks 2026-10-18 13:31:56 -07:00
Malte UblandClaude Opus 5.5 78100a4124 Record ts7 order baselines for the new CommonJS corpus programs
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>
2026-10-18 13:29:28 -07:00
Malte UblandClaude Opus 5.5 fbcdb1d641 Compile inline require(), computed and chained CommonJS exports, and a module's own exports object
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>
2026-10-18 13:29:28 -07:00
Chris Tate 3be66127c2 Fence refused statements inside capture buffers instead of dropping them (#1322) 2026-10-18 15:24:10 -05:00
Chris Tate 547e59529f Resolve builtin classes through const aliases
`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.
2026-10-18 15:23:20 -05:00
Malte UblandClaude Opus 5.5 d7fcc9287c Merge origin/main into opt/gc-nursery
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>
2026-10-18 13:14:30 -07:00
Chris Tate 6ea39a9c2f Merge main 2026-10-18 15:11:07 -05:00
Malte UblandClaude Opus 5.5 a2707ac8d6 Name the inner location in package-anchored npm-static refusals
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>
2026-10-18 13:07:01 -07:00
Malte UblandClaude Opus 5.5 c20c21b22c Declare the deferred fences of 6110 for the coverage contract
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>
2026-10-18 13:05:47 -07:00
Chris Tate b866ae3236 Report refused local classes from speculative type queries again (#1321) 2026-10-18 15:04:40 -05:00
Malte UblandClaude Opus 5.5 7ab6e8c626 Store typed-array elements through storage wider than a typed array
`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>
2026-10-18 13:04:21 -07:00
Malte UblandClaude Opus 5.5 6d6a140064 Lower a JavaScript class method that reads itself as a value once
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>
2026-10-18 13:04:20 -07:00
Malte UblandClaude Opus 5.5 8aa69ad169 Stop checking the storage fill of early-reachable let globals
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>
2026-10-18 13:04:20 -07:00
Malte UblandClaude Opus 5.5 147013d7b9 Merge origin/main into opt/npm-small-fixes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:58:58 -07:00
Malte UblandClaude Opus 5.5 40c56b96ce Merge origin/main into opt/npm-small-fixes
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>
2026-10-18 12:58:53 -07:00
Malte UblandClaude Opus 5.5 26b703a821 Keep React Flight's development-only stack parsing out of production builds
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>
2026-10-18 12:44:31 -07:00
Chris Tate 526415a91c Give matchAll rows and exec results their index, input and groups
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.
2026-10-18 14:43:40 -05:00
Chris Tate 1c1400272f Keep the compiler's kind and code methods direct (#1317) 2026-10-18 14:43:02 -05:00
Chris Tate 42591b1eed Read zlib options held in typed objects (#1316) 2026-10-18 14:24:54 -05:00
Chris Tate 470d317703 Keep class methods named kind and code direct in the compiler
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.
2026-10-18 14:21:32 -05:00
Malte UblandClaude Opus 5.5 700f59c1b2 Serve Temporal's absence, v8, stream/web, dns/promises, EvalError and graceful-fs
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>
2026-10-18 12:11:05 -07:00
Chris Tate 240f576805 Add execution tiers to the IR and a report-only tier analysis (#1315) 2026-10-18 14:08:12 -05:00
Malte UblandClaude Opus 5.5 5746dc30c5 Expect the compile to refuse stream-shims and node24-file-url-conversion again
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>
2026-10-18 12:05:40 -07:00