An untyped package another package's JavaScript imports is selected
whether resolution answers no declarations or its JavaScript. A
DefinitelyTyped twin qualifies by identity (@types/<mangled name>):
the declarations only check the program, and the JavaScript compiles
with its inferred surface, so a twin that disagrees with the shipped
JavaScript fails the build at the use rather than compiling against it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An __esm initializer becomes a run-once closure over its body in the
bundle's own scope. Interop bindings it assigns once from require()
become that require at the assignment, with their member reads respelled
as reads of the required module; a namespace read only through members
becomes an object literal of getters over the module's live bindings.
Asynchronous initializers, initializer results, and namespaces kept as
values (a memoized lazy loader) stay refused with a message naming them.
The default selection now also compiles a package typed by a
DefinitelyTyped twin that describes its installed release (same major,
or major.minor below 1.0), and untyped dependencies of compiled
packages. A twin for another release is refused with both versions.
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>
A require cycle was always refused (SC1016). Node answers a require of a
module that is still evaluating with its exports as they stand, while the
compiled bindings alias the final declarations; the two agree when every
module of the cycle assigns all of its exports before its first statement
that can run another module's code, every other use of its export object
is a plain member read, and no module's top-level code can reach its
binding of another member. Each module then initializes exactly as it
would outside the cycle. This admits semver's comparator/range cycle
("hoisted class for cyclic dependency"); other cycles keep SC1016 with a
reason naming the offending statement.
The require reachability scan no longer treats a declaration's own name
as a read (esbuild's `var X = class {...}` before its requires), treats a
plain write of an export member as running only a setter published for it
(on-finished's `module.exports.isFinished = isFinished`), and keeps the
conservative scan for writes of __proto__, __esModule and members of a
replaced export object.
Evidence: corpus 6145 (the cycle), 6142 gains the esbuild layout; the
npm-static harness compiles the published fs.realpath@1.0.0,
on-finished@2.4.1 (with ee-first@1.1.1) and statuses@2.0.1 statically;
program.test.ts pins the TDZ analysis through var bindings plus the cycle
admission and refusals. Preflight/order baselines recorded for the new
fixtures; a full re-record changed no other fixture. Dependencies and
limitations docs describe the supported require forms.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Node runs TypeScript with verbatimModuleSyntax semantics: `import type` and
`export type … from` vanish, while `import { type A }` and
`export { type A } from` keep an empty clause and still load their module.
- Package selection skipped nothing: `import type { X } from "type-fest"`
selected type-fest and failed with SC2013, and type imports pulled whole
packages into the compile. Erased edges no longer select packages.
- Files reached only through erased edges are no longer program modules,
so their imports (a `node:vm` import, say) no longer fence the build.
- Inline type-only clauses are real module edges again (their modules'
side effects ran under Node but not in the binary); a cycle closed by
one binds nothing and is admitted like a side-effect import.
- Interfaces, type aliases and type literals from an installed package's
declarations map structurally, so values the program builds with a
type-only package's types compile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A package function that destructures its options object, such as
makeClass({ Base, name }), now specializes per call site like positional
parameters: each destructured name binds the static type of the matching
property, so a class passed as { Base } keeps its static type and
class extends Base builds a constructible subclass.
Fixes#938
Co-authored-by: phall <25888173+phall1@users.noreply.github.com>
A static method that a function-local JavaScript class defines at
runtime and a program class inherits (Animal.extend("Dog")) is now
called directly with this bound to the receiver class when it captures
nothing from the factory's scope, so the subclass it builds has a static
base and constructs like Node.
Fixes#938
Co-authored-by: phall <25888173+phall1@users.noreply.github.com>
* Expand static compilation for common Effect 4 patterns
* Run every Effect 4 fixture slice in CI
* Preserve existing corpus behavior across Effect 4 lowering
* Preserve Effect platform callbacks and native stream state
* Record new corpus baselines and retain child stdin refusals
* Retire the obsolete stateful regex diagnostic
* Preserve promise reference count layout for cycle collection
* feat: support static buffer constructors and prototype methods
- Preserve typed-array constructor identity and shared storage across JavaScript class APIs.
- Support chained indexed assignments and mutable prototype methods with native receiver dispatch.
- Compile Three.js geometry merging, instancing, and keyframe interpolation without a JavaScript engine.
* fix: preserve native collection and dispatch semantics
- Preserve typed-array identity in collections and JavaScript argument evaluation.
- Keep symbol-backed fields and unreachable methods on their existing static paths.
- Restore compiler bootstrapping and deferred class diagnostics.
* fix: preserve inferred returns in native compilation
- Update recorded return statements in place so native compilation preserves mixed JavaScript return values.
* test: update inferred array coverage expectations
- Recognize heterogeneous writes supported by shared JavaScript array storage.
- Compile mesh, line, and point picking with perspective and orthographic camera rays.
- Preserve JavaScript override arguments, array identity, and native subclass values across checked calls.
- Specialize package class helpers and handle unsupported JSDoc namepaths.
- Keep cached native class instances callable, including inherited methods and JavaScript arguments.
- Support plain-object Proxy traps with live receivers, enumeration, and data-property invariants.
- Compile untyped addition, computed environment keys, and text-codec startup storage natively.
- Share symbol-keyed global caches across statically compiled modules.
- Preserve assignment results and evaluation order for native fields, accessors, and nullish defaults.
- Read omitted options correctly in specialized JavaScript package calls.
- Compile Unicode code-point construction, scalar iterable inputs, and primitive Buffer predicates without a JavaScript engine.
- Preserve object identity and property additions or deletions in inferred JavaScript locals.
- Recover nullable class fields initialized through static factories in bundled packages.
- Preserve nullable class fields and module callbacks in native storage with correct initialization behavior.
- Support typed-array construction, bulk copying, and in-place compaction through checked native values.
- Preserve receiver identity and evaluation order in nested field updates.
- Compile zero-argument callback fields and derived arrow replacements using their declared nullable type.
- Preserve callback captures, identity, and null resets in native class storage.
- Carry declaration-backed string, number, and boolean method results into static JavaScript compilation.
- Match named class re-exports to their implementations while preserving self types and rejecting ambiguous aliases.
- Preserve native virtual dispatch when an override omits trailing checked-value parameters.
- Keep argument side effects and subclass defaults correct across direct, inherited, and super calls.
- Keep fields, accessor parameters, and return values inferred as undefined in native checked storage.
- Preserve virtual dispatch for overridden methods in JavaScript packages.
- Route assignments through class accessors without creating shadow fields.
- Statically resolve stable let/var createRequire bindings while rejecting mutation, escape, and early use.
- Compile node:console output methods to native process streams and retain explicit custom Console refusals.
- Extend native FFI with additional scalar widths and writable byte spans.
- Compile stored text codecs and supported bundled module patterns without a JavaScript engine.
- Document supported limits.
* Enable initial static compilation of published Effect modules
- Compile the published Effect Function subpath and deeper npm module chains as static program code.
- Preserve JavaScript argument and string search behavior across native backends, with differential coverage.
* Prune unused static npm namespace re-exports
- Honor package sideEffects metadata across nested ESM scopes and pure dependencies.
- Keep preflight, linking, and initialization consistent, with Node differential coverage.
* Fix static npm pruning across dependency cycles
- Make package purity caching safe across dependency cycles.
- Cover transitive module initialization with a Node differential fixture.