Documentation content

Coverage Reports

scriptc coverage tells you how much of a program compiles before you build it. Use it when you bring an existing Node.js program to scriptc, add a dependency, or want CI to catch unsupported code early. It analyzes the program without producing an executable, counts the statements that compile, and groups anything unsupported by diagnostic code with a location and a hint.

Run a report

Pass the program's entry file:

$ cat hello.ts
const who: string = process.argv.length > 2 ? process.argv[2] : "world";
console.log(`hello, ${who}`);

$ scriptc coverage hello.ts

  statements analyzed   2
  compile statically    2  (100%)

  fully static — all analyzed statements compile to native code.

Every statement in this program compiles, so scriptc build will succeed. The counts describe this program only, not JavaScript or Node.js support in general.

Reading the report

When a program has unsupported operations, the report adds a group for each root cause. A group shows the diagnostic code, the reason, the first few sites in source order, and a hint. A generic declaration that fails for several type arguments appears once.

FieldMeaning
statements analyzedExecutable statements in application code, excluding dependency implementation code.
compile staticallyStatements that compile to native instructions.
blockersUnsupported operations with counts, diagnostic codes, reasons, locations, and hints.
in unreached codeBlockers in code the entry never reaches. A build never compiles that code, so these cannot fail it.
differs from NodeSites that compile but can behave differently from Node.js. See Node divergences.
npm package compilationNative package compilation outcomes and refusal reasons.

Blockers in unreached code and deferred operations in JavaScript packages are listed separately because they don't fail a build. A deferred operation throws a runtime error if it runs, so a successful build doesn't mean every API of a package works; see unsupported code inside a package.

If a function's signature can't compile, the statements in its body count as not compiling, so the percentage reflects how much of the program compiles.

Diagnostic codes

Coverage and scriptc build report the same diagnostic codes. Common ones include:

  • SC2020: a declared standard-library or Node.js API has no supported compiler implementation.
  • SC2012: this API form cannot compile natively.
  • SC2013: a package cannot compile natively; inspect the package-specific reason and the dependency guide.
  • SC1100: a value whose type is only known at runtime, such as unknown, is used where scriptc needs a specific type. Narrow or cast the value as the diagnostic suggests.

Node divergences

Some code compiles but can behave differently than under Node.js. Coverage reports the cases it can detect as SC6xxx warnings, and scriptc build prints the same warnings after a successful build. They never fail a build, but --fail-on=divergences can fail a CI job on them.

  • SC6001: a record passed to, stored as, asserted as, or stored as an array element of a record type with different properties is copied, and the program then writes through the copy or compares it by identity.
  • SC6002: an object literal's key order differs from its type's declaration order, and the program observes the order through JSON.stringify, Object.keys, Object.values, Object.entries, for...in, or console output.
  • SC6003: localeCompare compares a string literal outside the built-in Latin-script collation.
  • SC6004: a call passes a class instance to a function that casts it to an unrelated class.
  • SC6005: a Date string literal uses a form the native parser does not accept.

Gating builds and CI

By default, scriptc coverage exits with status 0 whenever the program type-checks, so you can use the report to track progress. To fail a CI job instead, add --fail-on:

$ scriptc coverage src/main.ts --fail-on=blockers

--fail-on=blockers exits with status 1 when the program has blockers that would fail scriptc build. Blockers in unreached code and deferred operations don't count. --fail-on=divergences also fails on Node divergences. A program that doesn't type-check always exits with status 1.

Coverage caches its result. Running it again on an unchanged program, or after edits that only touch comments, reuses the previous verdict. Set SCRIPTC_NO_CACHE=1 to turn the cache off.

Machine-readable diagnostics

For editors, CI annotations, and other tools, scriptc coverage --print=diagnostics and scriptc build --print=diagnostics write one JSON document to stdout instead of the human-readable report. The exit status is unchanged. The document looks like this:

{
  "schema": "scriptc-diagnostics",
  "schemaVersion": 1,
  "compilerVersion": "0.3.0",
  "command": "coverage",
  "entry": "/work/app/src/main.ts",
  "success": false,
  "phase": "compile",
  "stats": {
    "statementsTotal": 13,
    "statementsStatic": 12,
    "statementsDynamic": 0,
    "statementsFailed": 1,
    "functionsSkipped": 0,
    "percentStatic": 92
  },
  "groups": [
    {
      "id": "SC1031-c2cc8425",
      "code": "SC1031",
      "category": "unsupported",
      "severity": "error",
      "scope": "reached",
      "message": "object destructuring of non-record values (the source is array-typed)",
      "hint": "...",
      "count": 1,
      "primary": { "file": "/work/app/src/main.ts", "line": 13, "column": 7 },
      "sites": [{ "file": "/work/app/src/main.ts", "line": 13, "column": 7 }]
    }
  ],
  "diagnostics": [
    {
      "code": "SC1031",
      "category": "unsupported",
      "severity": "error",
      "scope": "reached",
      "file": "/work/app/src/main.ts",
      "line": 13,
      "column": 7,
      "endLine": 13,
      "endColumn": 28,
      "start": 352,
      "end": 373,
      "message": "object destructuring of non-record values (the source is array-typed) are not supported yet",
      "hint": "...",
      "group": "SC1031-c2cc8425"
    }
  ]
}
FieldMeaning
schemaVersionIncremented when a field is renamed or removed or its meaning changes. New optional fields, categories, and codes keep the version.
successCoverage: no blockers on the entry path (and, with --fail-on=divergences, no divergences). Build: an artifact was produced, named by artifact.
phasepreflight when type checking, configuration, or the module graph stopped the command; compile when blockers remain; native when native code generation or linking failed; otherwise complete.
statsCoverage only, absent after a preflight failure: the report's statement counts. statementsDynamic is always 0 and remains for schema compatibility.
categoryinvalid-source (the program has a TypeScript or JSON error), unsupported (valid code scriptc cannot compile yet), divergence (compiles, but can behave differently from Node.js), environment (project configuration, scriptc's type world, toolchain, or target), or internal (a compiler bug).
severityerror, or warning for divergences.
scopepreflight, reached (fails a build), unreached (code the entry never reaches), or deferred (a JavaScript statement that compiles to a throw of its diagnostic, which happens only if it executes).
line, column1-based line and UTF-16 column; start and end are 0-based UTF-16 offsets.
groupThe id of the root-cause group the diagnostic belongs to. A group's primary site is its first in source order.

Type errors

Coverage needs a program that type-checks. If type checking fails, the report lists the type errors instead of statement counts; fix them first.

scriptc type-checks with its own settings: strict null checks, the ES2025 library, and Node.js types (its bundled declarations when the project has no @types/node). An error those settings cause, rather than the project's own tsc configuration, carries a hint naming the cause, such as a library member newer than ES2025 or a global of another runtime, and machine-readable output reports it in the environment category.

External host type declarations

When your code will run inside a host application that provides its own modules, those modules aren't in node_modules. Use --external-types to give coverage their declarations so it can analyze the rest of your code:

$ scriptc coverage src/core.ts --external-types @native-sdk/core=types/native-sdk-core.d.ts

The option is repeatable. Relative declaration paths resolve from the current working directory. Supported declaration extensions are .d.ts, .d.mts, and .d.cts. Relative declaration imports and re-exports are included, so the mapped file can be an index.d.ts barrel. Project-owned code using these types participates in coverage; type-only imports add no runtime boundary.

The mapping supplies types for analysis, not a runtime implementation. Value imports and uses remain SC1010 external-host blockers while analysis counts the rest of the application. This option is available only for coverage; builds require a module implementation or runtime integration.