Skip to content

[ETS] Preserve TypeScript structural object types - #363

Merged
CaelmBleidd merged 9 commits into
neofrom
caelmbleidd/native-ts-call-targets
Aug 22, 2026
Merged

[ETS] Preserve TypeScript structural object types#363
CaelmBleidd merged 9 commits into
neofrom
caelmbleidd/native-ts-call-targets

Conversation

@CaelmBleidd

@CaelmBleidd CaelmBleidd commented Aug 21, 2026

Copy link
Copy Markdown
Member

What changed

  • Preserve property-only object type literals as synthetic TYPE_LITERAL classes instead of degrading them to UnknownType. Field names, field types, modifiers, optional markers, and recursive references are retained.
  • Preserve the TypeScript object keyword as an empty structural TYPE_LITERAL class.
  • Emit each structural class only in its declaring file. Importing files reference the same source-based signature without emitting duplicate class definitions.
  • Preserve generic structural aliases in declaration form and attach concrete type arguments at use sites. This also works when the type literal is reached through another alias, rather than appearing as the alias target directly.
  • Pin Node.js 20.20.2 in .nvmrc for frontend tests and publication workflows.
  • Provision the same Node.js version for JitPack through a dedicated fail-fast bootstrap script. The script retries transient downloads, verifies a fixed SHA-256 before extraction, and validates both node and npm before Gradle publishes the bundled frontend.

Type literals containing unsupported or computed members still fall back to UnknownType as a whole, so the frontend does not expose a misleading partial shape.

Why this is needed

The native TypeScript frontend should preserve source type information without imposing runtime interpretation policy on downstream analyses. Previously, structural annotations lost their fields, imported structural types could be emitted more than once with the same signature, and generic shapes could be specialized by whichever use site happened to be lowered first.

The emitted EtsIR now has one stable, declaration-owned structural entity, while each use carries its own type arguments. Type-level anonymous structures (TYPE_LITERAL) remain distinct from runtime object literals (OBJECT).

Building jacodb-ets now also builds and packages the native frontend. JitPack images do not provide npm, so without the pinned toolchain the Gradle build stopped at :jacodb-ets:installTsFrontend and produced no dependency artifacts for downstream projects.

Verification

  • npm test: 212 frontend tests passed.
  • npm run build: TypeScript checking, bundling, and runtime packaging passed.
  • USVM integration against this JacoDB branch passed:
    • :usvm-ts:test;
    • :usvm-ts-dataflow:test.
  • JitPack published commit feb74bcb07 successfully:
    • all eight published JacoDB module POMs are available;
    • the published jacodb-ets JAR contains ets-frontend/runtime.zip, including index.js and the TypeScript standard-library declarations.

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Test Results

  225 files  ±0    225 suites  ±0   15m 47s ⏱️ -55s
  776 tests ±0    764 ✅ ±0  12 💤 ±0  0 ❌ ±0 
2 046 runs  ±0  1 996 ✅ ±0  50 💤 ±0  0 ❌ ±0 

Results for commit feb74bc. ± Comparison against base commit c4f57f0.

♻️ This comment has been updated with latest results.

@CaelmBleidd
CaelmBleidd force-pushed the caelmbleidd/native-ts-call-targets branch from 7884d06 to 80a8a9b Compare August 21, 2026 15:32
@CaelmBleidd CaelmBleidd changed the title Native ts call targets [ETS] Preserve TypeScript structural object types Aug 21, 2026
@CaelmBleidd
CaelmBleidd merged commit 9ea3387 into neo Aug 22, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant