Compiler milestone

How VexaScript compiles itself to JavaScript

Commit a1c776d6 added the first complete JavaScript self-hosting test on June 17, 2026. The test compiles the real TypeScript CLI, runs the result, and uses that generated compiler to compile itself again.

How the test works

The input is cli/cli-bin.ts and all of its local dependencies. It is not a smaller compiler made only for the test.

TypeScript source compiler
  -> JavaScript compiler 1
  -> JavaScript compiler 2
  -> JavaScript compiler 3
  -> compare compiler 2 and 3
  -> compile and run testFixtures/sample.vx
Check Purpose
Full CLI graph Covers the real parser, analyzer, resolver, and emitter
Isolated output directory Prevents a fallback to the source CLI
Three generations Finds output that changes after each compilation
Byte and SHA-256 comparison Requires stable compiler output
Final fixture run Confirms that the last compiler works

The repository runs this workflow with pnpm self-host and covers it in an automated test.

Removing a false success

The development CLI can delegate to the source TypeScript entrypoint when it runs inside the repository. This made a broken generated compiler appear to work.

Each generated compiler now runs from an isolated directory. It cannot find the development entrypoint, so the generated bundle must do the work itself.

Problems found by the full compiler

Problem Fix
An object literal inside as const produced invalid arrow syntax Check through type-only wrappers before adding parentheses
baseUrl imports became external packages Keep baseUrl in project resolution data
Dotted filenames were not found Probe known source extensions after dotted basenames
A Node build rejected node:child_process Add an explicit Node bundle platform
Generated compilers used the source CLI Run every generation in isolation

These fixes also help ordinary TypeScript projects. None is special handling for the compiler source.

TypeScript remains the semantic checker

At first, self-hosting used an explicit transpile-only mode because VexaScript did not understand every advanced TypeScript type in the compiler and Node.js declarations.

The current flow runs tsc --noEmit for .ts and .tsx projects. After that check passes, VexaScript performs the work needed for binding, lowering, bundling, and JavaScript generation. .vx files still use VexaScript's own diagnostics.

The initial change touched eight files, with 127 additions and 45 deletions. Its main value is the integration test: the compiler must preserve enough of its own behavior to reproduce a stable compiler three times.