fix(api-manifest): closes #513 — enumerate every native module so R005 covers 100% of supported surface (v0.5.600) - #523
Merged
Merged
Conversation
…5 covers 100% of supported surface (v0.5.600) The unimplemented-API gate from #463 is `module_has_any_entries(M) && module_has_symbol(M, prop).is_none()` — modules with zero manifest entries silently fell through to the old permissive behaviour, leaving the same class of bug Justin hit in #455 alive on un-enumerated modules. ~20 modules in NATIVE_MODULES had zero entries (`fs`, `util`, `stream`, `child_process`, `tty`, `http`, `https`, `axios`, `node-fetch`, `bignumber.js`, `node-cron`, `perry/ui`, `perry/system`, `perry/i18n`, `perry/updater`, `perry/media`, `perry/plugin`, `perry/widget`); five well-known aliases (`redis` / `date-fns` / `streams` / `rate-limiter-flexible` / `fetch`) weren't even registered as native modules. Three coordinated changes: 1. `crates/perry-api-manifest/src/entries.rs` — backfill ~250 entries covering the gap modules. perry/ui + perry/system + perry/i18n + perry/updater + perry/media are auto-derivable from PERRY_*_TABLE in crates/perry-dispatch; perry/plugin from PERRY_PLUGIN_TABLE in crates/perry-codegen/src/lower_call.rs. fs / util / stream / child_process / tty / buffer / url get method+class entries reflecting what perry-runtime + perry-stdlib actually implement. The HTTP-client trio (axios / node-fetch / http / https) covers the standard verb methods plus class constructors. The well-known aliases (redis / date-fns / bignumber.js / node-cron / streams / rate-limiter-flexible / fetch) get entries mirroring their canonical module so `import { Redis } from 'redis'` works the same way as `import { Redis } from 'ioredis'`. Coverage went from 397 entries / 45 modules to 638 entries / 64 modules. 2. `crates/perry-codegen/tests/manifest_consistency.rs` — two new reverse-direction drift tests. `every_native_module_has_at_least_one_manifest_entry` walks NATIVE_MODULES and asserts each one has at least one manifest entry (allow-list: `dotenv/config`, side-effect-only sub-path with no value binding). `every_well_known_binding_has_manifest_entry` parses well_known_bindings.toml and asserts each routed module name has manifest coverage. Both fail loudly with the missing module names + the fix recipe, so adding a future native module without manifest entries breaks CI before the PR ships. 3. `crates/perry-hir/tests/unimplemented_api_check.rs` — new `every_supported_module_rejects_bogus_member` parity sweep that compiles `import * as m from "<module>"; const x = m.__perry_known_bogus_member_513__;` for every entry in NATIVE_MODULES and asserts the R005 / #463 error fires (skip list: `dotenv/config` + the external `tursodb` / `iroh` bindings whose value-binding shape doesn't trigger the gate in the isolated HIR test). The previously-permissive `module_with_no_manifest_entries_is_permissive` test that documented the pre-#513 fall-through is replaced with `supported_module_with_unknown_member_is_rejected`. End-to-end smoke verified: `import * as fs from "fs"; const x = fs.bogusMethod;` errors with the R005-style message naming the offending property; `import * as ui from "perry/ui"; ui.bogusWidget;` errors identically; legitimate `fs.writeFileSync(p, "ok")` + `path.join("/tmp", "x")` continue to compile + run unchanged. docs/src/api/reference.md (now 638 entries / 64 modules) and docs/api/perry.d.ts regenerated through scripts/regen_api_docs.sh — the api-docs-drift CI gate from v0.5.560 keeps these in sync going forward. Closes the credibility gap from #513's "v0.5.585 release implies completeness it doesn't have yet" framing — `perry --print-api-manifest` now genuinely reflects the supported surface, and a user on `async_hooks` / `dgram` / etc. gets the same #463 compile-time error every other module produces.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #513 (followup to #463). The unimplemented-API gate was conditioned on
module_has_any_entries(M) && module_has_symbol(M, prop).is_none()— modules with zero manifest entries silently fell through to the old permissive behaviour, leaving the same class of bug Justin originally hit oncrypto.subtlein #455 alive on un-enumerated modules. ~20 modules inNATIVE_MODULEShad zero entries; five well-known aliases weren't even registered as native modules.This PR ships:
Backfill in
crates/perry-api-manifest/src/entries.rs— ~250 new entries covering the gap modules (fs,util,stream,child_process,tty,http,https,axios,node-fetch,bignumber.js,node-cron,perry/ui,perry/system,perry/i18n,perry/updater,perry/media,perry/plugin,perry/widget, plus the well-known aliasesredis/date-fns/streams/rate-limiter-flexible/fetch). perry/ui + perry/system + perry/i18n + perry/updater + perry/media are auto-derived fromPERRY_*_TABLEincrates/perry-dispatch. Coverage went from 397 entries / 45 modules to 638 entries / 64 modules.Reverse-direction drift tests in
crates/perry-codegen/tests/manifest_consistency.rs:every_native_module_has_at_least_one_manifest_entry— walksNATIVE_MODULES, fails CI if any entry has zero manifest rows (allow-list:dotenv/config, side-effect-only sub-path).every_well_known_binding_has_manifest_entry— parsescrates/perry/well_known_bindings.toml, fails CI if any routed module name lacks manifest coverage.R005 parity sweep in
crates/perry-hir/tests/unimplemented_api_check.rs::every_supported_module_rejects_bogus_member— compilesimport * as m from "<module>"; const x = m.__perry_known_bogus_member_513__;for everyNATIVE_MODULESentry and asserts the R005 / Compile-time error for unimplemented Node / Web APIs #463 error fires.The previously-permissive
module_with_no_manifest_entries_is_permissivetest that documented the pre-#513 fall-through is replaced withsupported_module_with_unknown_member_is_rejected, asserting the new strict behaviour.docs/src/api/reference.mdanddocs/api/perry.d.tsregenerated throughscripts/regen_api_docs.sh— theapi-docs-driftCI gate from v0.5.560 keeps these in sync going forward.Test plan
cargo test --release -p perry-codegen --test manifest_consistency— 4 / 4 pass (2 new reverse-direction tests).cargo test --release -p perry-hir --test unimplemented_api_check— 8 / 8 pass (1 replaced + 1 new parity sweep test).cargo test --release -p perry-api-manifest— 7 / 7 pass.fs.writeFileSync(p, "ok")+path.join("/tmp", "x")continue to compile + run;fs.bogusMethoderrors with the R005-style message;perry/ui.bogusWidgeterrors identically../scripts/regen_api_docs.sh— produces no further diff after running with the manifest changes (drift gate happy).test_edge_destructuring,test_edge_objects_records,test_gap_object_methods) / 1 known compile fail (test_issue_446_import_type_method_typeof) / 13 skipped. The 3 jsruntime-related compile fails surfaced in the worktree becauselibperry_jsruntime.awasn't pre-built — environmental, not a regression.Refs #455, #463, #466 (Phase 2 — adding new modules now auto-enrolls them via the reverse drift gate).