Skip to content

API manifest: enumerate remaining stdlib modules so unimplemented-API check (#463) covers 100% of supported surface #513

@proggeramlug

Description

@proggeramlug

Followup to #463 / #455 DX thread.

The compile-time R005 UnimplementedApi check from #463 only fires for modules whose surface has been enumerated in crates/perry-api-manifest/src/entries.rs::API_MANIFEST. The check in crates/perry-hir/src/lower/expr_member.rs + lower/expr_call.rs is gated on module_has_any_entries(M) — modules with zero entries stay permissive (silent undefined for any property access on them), so the same class of bug Justin hit in #455 can still occur on un-enumerated modules.

Today's coverage: 397 entries across 45 modules (per --print-api-manifest=markdown). Solid but not 100% of node:*.

Concrete gaps to enumerate

Need to audit crates/perry-stdlib/src/lib.rs + crates/perry-codegen/src/.../NATIVE_MODULE_TABLE and reconcile against API_MANIFEST. The drift test crates/perry-codegen/tests/manifest_consistency.rs currently checks one direction (every dispatch row has a manifest entry). It should also check the reverse: any pub mod X; in perry-stdlib without a corresponding manifest entry is a coverage gap that fails CI.

Likely candidates (need verification):

  • Modules whose dispatch routes through custom Expr::* HIR variants (per Compile-time error for unimplemented Node / Web APIs #463 the manifest already hand-covers crypto / os / path / process — others may exist).
  • New wrappers added under Native package ecosystem v1: open, extensible, with zero developer-facing change #466 Phase 5 — every new perry-ext-* crate should add its module to the manifest as part of the port, but this isn't enforced.
  • node: prefix variants (node:fs, node:path, …) — should resolve to the same manifest entries as the bare names. Worth a unit test.
  • Web globals at module scope (fetch, URL, URLSearchParams, TextEncoder, …) — these aren't imports, so the property-access path is different. Some flow through Expr::PropertyGet { object: Identifier, ... } rather than NativeModuleRef. Needs separate gating logic.

What "done" looks like

  1. Reverse-direction drift test in manifest_consistency.rs enumerates every pub mod in perry-stdlib + every perry-ext-* workspace member's exports + every native-method dispatch table. Any name without a manifest entry fails CI.
  2. module_has_any_entries(M) returns true for every supported module, so the permissive fall-through becomes unreachable in practice.
  3. A new test in tests/parity/ compiles a TS file that imports each supported module and references a known-bogus symbol, asserting R005 fires.

Why this matters

#463 is shipped and works on the modules it covers, but the framing in the v0.5.585 release ("compile-time error for unimplemented APIs") implies completeness it doesn't have yet. A user on a less-trodden module (async_hooks, dgram, tls.createSecureContext, …) gets the old silent-undefined experience, doesn't know why, and loses the same hours Justin lost.

Refs: #455, #463 (closed), #466 (Phase 2 — adding new modules should auto-enroll them).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions