Skip to content

Tracker: AOT-first eval/new Function strategy — evaporate runtime dynamism at build time #1677

Closed

Description

@proggeramlug

Goal

Make Perry handle eval / new Function the way an AOT compiler should: never execute a code-string at runtime. Every legitimate case is resolved at or before build time, so the runtime JS engine (perry-jsruntime / embedded V8) becomes deletable from shipped binaries.

What the investigation found (verified against vendored sources)

Conclusion: a runtime interpreter ("PerryVM") has no use case here. The only place an evaluator is needed is build time, and we already own one (V8) — so the move is to demote V8 to a build-time tool, not embed it at runtime.

Phases (strictly gated)

Each phase must be merged to main and parity-green before the next is started. No parallel work across phases.

End state

A Perry binary that links no runtime JS engine, where:

  1. constant code-strings became native functions (P1),
  2. schema/template codegen libraries ran at build time and emitted native code (P2/P3),
  3. the few imperative-runtime JITs have native equivalents (P4),
  4. anything left over is a clear compile error naming the package and call site (P0).

Activity

  1. proggeramlug commented on May 26, 2026

    @proggeramlug
    ContributorAuthor

    Wrap-up — core strategy delivered

    The AOT-first eval/new Function strategy is implemented and merged through Phase 3. The headline result: Perry evaporates build-time-knowable dynamism at build time, with no runtime JS engine and no external build dependency — by compiling and running its own output.

    Phase Outcome PR
    0 — classify new Function/eval + precise refusal merged #1776 (#1678)
    1 — const-fold literal bodies → native merged #1783 (#1679)
    2 — perry.codegen build-time convention + ajv/standalone merged #1801 (#1680)
    3 — self-hosted build-time precompile() (Perry runs its own codegen, no node/V8) merged #1814 (#1681)

    Boundary (by design): literal bodies → fold (P1); build-time-knowable codegen → self-hosted precompile (P3); genuinely-runtime new Function(runtimeData)/eval(userInput) → refused (P0). An AOT binary can't honestly fake runtime dynamism — the refusal is the correctness guarantee.

    Remaining, tracked separately (closing this tracker):

    These become a focused GC/codegen-correctness workstream rather than open tracker items.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew capability or improvement

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions