Coverage Reports

scriptc coverage answers "how much of my program compiles to native code?" It analyzes the program without building it and assigns every statement to a tier. No global scoreboard, no hand-waving: the numbers are for your program, and every non-static site is named with an error code.

A fully static program

$ scriptc coverage app.ts

  statements analyzed   10
  compile statically    10  (100%)

  fully static — this program has no dynamic remainder.

This is the common case for typed application code: the whole program becomes native code, and a scriptc build binary carries no engine.

A program with a dynamic remainder

Import an npm package and the report changes shape:

$ scriptc coverage cli.ts

  statements analyzed   4
  compile statically    3  (75%)

  runs with --dynamic   2 sites (embeds a JS engine, ~620KB — static stays the default)
      ×1  importing 'picocolors' requires the embedded dynamic engine, which this build does not include — the package's implementation runs there  SC2013
      ×1  values from the 'picocolors' package run in the embedded dynamic engine, which this build does not include                                SC2013

Reading it line by line:

LineMeaning
statements analyzedEvery executable statement in your program (not in dependencies).
compile staticallyStatements that become native code — no engine involved.
runs with --dynamicSites that would run in the embedded engine if you rebuilt with --dynamic. Without the flag, each is a compile error — this build does not include an engine, and never will silently.
blockersStatements that compile in no tier yet, each with a count, a one-line reason, and its SC code. These are the rejected tier: rebuilding with --dynamic does not make them go away.

The --dynamic view

scriptc coverage --dynamic answers a different question: what would a --dynamic build compile, and what still blocks it?

$ scriptc coverage cli.ts --dynamic

  statements analyzed   4
  compile statically    3  (75%)
  compile dynamically   1  (25%) (island sites — the embedded engine runs them)

  builds with --dynamic — no remaining blockers (the island sites above run in the embedded engine).

The closing line is the actionable verdict: this program builds with --dynamic. When it doesn't, the remaining blockers are listed exactly like the static view's.

The embedded-builtins report

When embedded npm code imports Node builtin modules, the --dynamic report says so — each builtin the embedded dependency graph reaches, whether it's shimmed inside the engine, and which package wanted it:

$ scriptc coverage tool.ts --dynamic

  statements analyzed   5
  compile statically    2  (40%)
  compile dynamically   3  (60%) (island sites — the embedded engine runs them)

  embedded npm code imports Node builtins:
    node:child_process  shimmed  (commander)
    node:events         shimmed  (commander)
    node:fs             shimmed  (commander)
    node:path           shimmed  (commander)
    node:process        shimmed  (commander)
    node:util           shimmed  (commander)

  builds with --dynamic — no remaining blockers (the island sites above run in the embedded engine).

The shims are reimplementations inside the engine, not Node itself — see npm Dependencies for what that means.

What the fences mean

Blocker lines carry SC codes — the same codes scriptc build errors with, so the coverage report and the compiler never disagree. A few common shapes:

  • 'X' is part of the standard library types but has no scriptc lowering yet (SC2020) — the type checker sees the full standard library, but only the supported surface compiles. The build error at that site includes the supported-alternatives hint.
  • importing 'pkg' requires the embedded dynamic engine (SC2013) — npm package implementations run in the engine; add --dynamic or drop the dependency.
  • 'fetch' runs in the embedded dynamic engine (SC2012) — island-backed ambient API: typed, callable from your code, executed by the engine.
  • passing 'unknown' values where 'any' is expected (SC1100) — the any/unknown boundary rules; narrow or cast first.

Type errors gate the analysis

Coverage only analyzes programs that typecheck. A program with TypeScript errors reports them instead of numbers:

$ scriptc coverage broken.ts

  not analyzable: 1 TypeScript error — fix type errors first (scriptc only analyzes programs that typecheck)

This is deliberate: tier assignment is driven by types, so numbers computed over an ill-typed program would be fiction.