Commit Graph
30 Commits
Author SHA1 Message Date
Malte UblandClaude Opus 5.5 0d9a6da8c9 Select untyped dependencies and @types twins by identity
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>
2026-10-19 14:19:07 -07:00
Malte UblandClaude Opus 5.5 f42fd146d9 Lower esbuild's lazy ES modules; select @types-typed packages by default
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>
2026-10-19 14:00:32 -07:00
Chris Tate 961d27802f Make selected npm packages join the type-checked program (#1331) 2026-10-18 16:57:35 -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 8597a364f6 Merge origin/main into opt/npm-small-fixes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:45:47 -07:00
Malte Ubl 8255315883 Merge origin/main into opt/cjs-interop 2026-10-18 06:46:23 -07:00
Malte UblandClaude Opus 5.5 ae91df908e Admit require cycles whose modules settle their exports first
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>
2026-10-18 06:24:04 -07:00
Malte UblandClaude Opus 5.5 d1639298ff Erase only import type edges, following Node's type stripping
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>
2026-10-17 19:39:16 -07:00
Chris Tate f291f1c275 Monomorphize destructured options parameters of package functions
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>
2026-10-17 20:50:59 -05:00
Chris Tate a5675b2279 Call factory-defined static methods with their receiver class
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>
2026-10-17 17:31:30 -05:00
Chris Tate e2d58f60d2 Expand static support for common Effect 4 patterns (#600)
* 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
2026-10-01 17:36:29 -05:00
Chris Tate 4d022037c3 feat: support static buffer constructors and prototype methods (#591)
* 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.
2026-09-30 17:53:59 -05:00
Chris Tate c257368c5e Compile Effect generators statically (#589)
* Compile Effect generators statically

* test: declare the dormant array write's expected fence
2026-09-30 14:25:29 -05:00
Chris Tate f818e8fb89 Extend static three.js support to raycasting
- 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.
2026-09-30 00:35:35 -05:00
Chris Tate fc6408a662 Compile native class caches and environment proxies
- 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.
2026-09-28 12:25:30 -05:00
Chris Tate 08115a1d3d Support native startup caches and assignment expressions
- 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.
2026-09-28 11:05:00 -05:00
Chris Tate 26b68b33d3 Support native keyboard parsing and factory-created class fields
- 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.
2026-09-28 10:34:39 -05:00
Chris Tate 76a086681a Support native byte queues and bundled JavaScript state
- 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.
2026-09-28 09:54:27 -05:00
Chris Tate f7f5c6197a Preserve declared nullable callbacks through bundled class inheritance
- 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.
2026-09-28 08:13:17 -05:00
Chris Tate 378eb2ffc6 Preserve declared scalar returns through bundled class aliases
- 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.
2026-09-28 07:55:21 -05:00
Chris Tate cac0a658f6 Compile JavaScript overrides that ignore trailing arguments
- 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.
2026-09-28 01:34:20 -05:00
Chris Tate f251066719 Preserve JavaScript class values and inherited behavior
- 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.
2026-09-28 01:16:59 -05:00
Chris Tate 37a25ebf7f Support stable bundled loaders and native console imports
- 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.
2026-09-27 22:20:25 -05:00
Chris Tate be1426a5cb feat(compiler): advance static OpenTUI support
- 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.
2026-09-27 21:49:40 -05:00
Chris Tateandvini 2d74c03adf fix(compiler): admit safe CommonJS export prologues (#482)
- Keep CommonJS packages eligible for static compilation when export prologues precede require calls.
- Preserve initialization order and early-access safeguards with frontend and native regression coverage.

Fixes #37

Co-authored-by: vini <91087061+vinikjkkj@users.noreply.github.com>
2026-09-26 23:52:23 -05:00
Chris Tate 266e22b151 Enable initial static compilation of published Effect modules (#428)
* 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.
2026-09-25 12:52:27 -05:00
Chris Tate e559808ef0 feat: run Commander actions statically (#330) 2026-09-15 16:30:54 -05:00
Chris Tate 5efda821cf feat(compiler): preserve npm static declaration overloads (#329) 2026-09-15 08:53:25 -05:00
Chris Tate b5f6b0dc46 Cite patterns, not target projects, across comments and hints
- Lowering rationale names the idiom; one user-facing hint reworded
- Diagnostics snapshot re-pinned to the neutral hint text
2026-07-23 01:18:50 -05:00
Chris Tate 23d5918a53 init 2026-07-22 18:08:04 -05:00