diff --git a/changelog.d/10618-tier-a-native-binding-removal.md b/changelog.d/10618-tier-a-native-binding-removal.md new file mode 100644 index 0000000000..c6fc6d55ce --- /dev/null +++ b/changelog.d/10618-tier-a-native-binding-removal.md @@ -0,0 +1,39 @@ +Removed the three Tier A native bindings that were safe to delete without +any compiler work: the bare-name `fetch` alias for `node-fetch`, and the +leftover in-tree accounting for `tursodb`/`iroh` (their actual crates and +`well_known_bindings.toml` entries had already moved out to +`@perryts/tursodb` / `@perryts/iroh` in v0.5.557 — this finishes the job). + +`fetch` alias: dropped `[bindings.fetch]` from `well_known_bindings.toml` +and the `"fetch"` entry from `NATIVE_MODULES`. `node-fetch` itself, its +`perry-ext-fetch` crate, and the manifest entries backing the built-in Web +Fetch API's `Response`/`Headers`/`Request`/`Blob`/`FormData` dispatch tag +(a separate mechanism, confirmed via the pre-existing +`builtin_fetch_usage_does_not_synthesize_well_known_fetch` test) are +unaffected; `"fetch"` moved to the test-only `INTERNAL_MODULE_KEYS` +allowlist so `known_modules_consistent_with_manifest` still holds. + +`tursodb`/`iroh`: removed their `NATIVE_MODULES` entries, manifest method +rows, `stdlib_features.rs` feature-gate arms, and skip-list entries in the +`unimplemented_api_check.rs` coverage sweeps. Their presence in +`NATIVE_MODULES` with no backing crate made the bare `import * as tursodb +from "tursodb"` specifier short-circuit past file resolution and silently +claim nativeness with nothing behind it — a dangling reference, not a +working feature. The real `@perryts/tursodb` / `@perryts/iroh` packages are +consumed via their scoped specifier, which was never in `NATIVE_MODULES` +and resolves through the unrelated `node_modules`/`perry.nativeLibrary` +path, untouched here. + +Regenerated `docs/src/api/reference.md`, `docs/api/perry.d.ts` (drop the +`tursodb`/`iroh` sections, keep `## fetch`), and +`docs/src/native-libraries/governance.md`'s generated table (`perry-ext-fetch`'s +package mapping drops `fetch`, keeps `node-fetch`). + +Validated: cargo tests on `perry-api-manifest`, `perry-hir`, `perry-codegen` +(`manifest_consistency`), and `perry`'s `stdlib_features`/`optimized_libs` +unit tests all green; `run_lint_gates.sh` 76/77 (the one red, +"Public benchmark evidence freshness", is pre-existing on every PR); +targeted gap suite (every fixture using `node-fetch` or built-in `fetch`) +at 100% parity; hand probes confirm `import * as tursodb from "tursodb"` +now fails at compile time with a clear error instead of compiling to a +broken no-op, and built-in `fetch`/`Response`/`Headers` still resolve. diff --git a/crates/perry-api-manifest/src/entries.rs b/crates/perry-api-manifest/src/entries.rs index 98d0061f8a..0e1415b629 100644 --- a/crates/perry-api-manifest/src/entries.rs +++ b/crates/perry-api-manifest/src/entries.rs @@ -54,8 +54,6 @@ pub const NATIVE_MODULES: &[&str] = &[ "mongodb", // MongoDB driver "better-sqlite3", // synchronous SQLite (replaces the N-API addon) "sqlite", // node:sqlite builtin surface - "tursodb", // Turso/libSQL client (legacy in-tree; now @perryts/tursodb) - "iroh", // iroh p2p (legacy in-tree; now @perryts/iroh) // #6562: Bun FFI (C-ABI). The `bun:` prefix is part of the specifier // (unlike `node:`, which is stripped) — `import { dlopen } from "bun:ffi"`. "bun:ffi", @@ -158,7 +156,6 @@ pub const NATIVE_MODULES: &[&str] = &[ // ── More third-party npm packages ── "redis", // npm `redis` client (aliases ioredis) "rate-limiter-flexible", // rate limiting - "fetch", // bare-name alias for the node-fetch surface // `undici` (#466) — served by perry's native fetch stack via the // bundled perry-ext-undici wrapper (ProxyAgent / Agent / // setGlobalDispatcher / getGlobalDispatcher / fetch subset). @@ -231,9 +228,13 @@ pub const NODE_SUBMODULES: &[&str] = &[ ]; /// Internal manifest keys used by dispatch/property gates but not importable -/// module specifiers. +/// module specifiers. `fetch` covers the built-in Web Fetch API's value-typed +/// dispatch tag (`Response`/`Headers`/`Request`/`Blob`/`FormData` + the bare +/// global `fetch()` call) — real fetch/HTTP-client I/O, distinct from the +/// removed bare-name `"fetch"` alias for the `node-fetch` npm package that +/// used to double as its NATIVE_MODULES entry (see well_known_bindings.toml). #[cfg(test)] -pub(crate) const INTERNAL_MODULE_KEYS: &[&str] = &["inspector.Network", "punycode.ucs2"]; +pub(crate) const INTERNAL_MODULE_KEYS: &[&str] = &["inspector.Network", "punycode.ucs2", "fetch"]; /// Modules handled entirely by `perry-runtime` — the linker doesn't /// need to pull in `perry-stdlib` for these. Migrated from diff --git a/crates/perry-api-manifest/src/entries/part_1.rs b/crates/perry-api-manifest/src/entries/part_1.rs index 8ccae06fe6..aa51556739 100644 --- a/crates/perry-api-manifest/src/entries/part_1.rs +++ b/crates/perry-api-manifest/src/entries/part_1.rs @@ -303,35 +303,6 @@ pub(crate) const API_MANIFEST_PART_1: &[ApiEntry] = &[ method("sqlite", "setAllowUnknownNamedParameters", true, None), method("sqlite", "sourceSQL", true, None), method("sqlite", "expandedSQL", true, None), - // tursodb (#424). open / exec / execBatch / close / - // lastInsertRowid / isAutocommit shipped in v0.5.543; queryAll / - // queryOne shipped in v0.5.553 (close the row-as-object gap by - // building shapes inside spawn_blocking and resolving with - // POINTER_TAG'd JsValues). - method("tursodb", "open", false, None), - method("tursodb", "exec", true, None), - method("tursodb", "execBatch", true, None), - method("tursodb", "queryAll", true, None), - method("tursodb", "queryOne", true, None), - method("tursodb", "close", true, None), - method("tursodb", "lastInsertRowid", true, None), - method("tursodb", "isAutocommit", true, None), - // iroh (#425). bind / nodeId / close shipped in v0.5.544; the - // peer connection + stream surface (connect / acceptOne / - // openBi / acceptBi / streamWrite / streamFinish / - // streamReadToEnd / connClose) shipped in v0.5.554. ALPN is - // hardcoded to `b"perry-iroh/0"` for v0. - method("iroh", "bind", false, None), - method("iroh", "nodeId", true, None), - method("iroh", "close", true, None), - method("iroh", "connect", true, None), - method("iroh", "acceptOne", true, None), - method("iroh", "openBi", true, None), - method("iroh", "acceptBi", true, None), - method("iroh", "streamWrite", true, None), - method("iroh", "streamFinish", true, None), - method("iroh", "streamReadToEnd", true, None), - method("iroh", "connClose", true, None), property("sea", "default"), method("sea", "isSea", false, None), method("sea", "getAsset", false, None), diff --git a/crates/perry-hir/tests/unimplemented_api_check.rs b/crates/perry-hir/tests/unimplemented_api_check.rs index a9120201d7..14fa823fbc 100644 --- a/crates/perry-hir/tests/unimplemented_api_check.rs +++ b/crates/perry-hir/tests/unimplemented_api_check.rs @@ -364,20 +364,11 @@ fn perry_native_namespace_rejects_unknown_call_in_strict_mode() { /// /// Side-effect-only sub-paths (`dotenv/config`) are skipped — they have /// no value binding to read properties off, so the gate doesn't apply. -/// `tursodb` and `iroh` are external bindings (live in standalone -/// `@perryts/*` repos as of v0.5.557) — their manifest entries exist -/// but the in-tree resolver doesn't recognise them as a `NativeModuleRef` -/// without `node_modules//package.json` declaring `perry.nativeLibrary`, -/// so the gate's prerequisite shape never triggers in this isolated -/// HIR test. #[test] fn every_supported_module_rejects_bogus_member() { const SKIP: &[&str] = &[ // Side-effect-only — no value binding to access. "dotenv/config", - // External (non-bundled) bindings — out-of-tree as of v0.5.557. - "tursodb", - "iroh", ]; let mut failures: Vec = Vec::new(); @@ -455,9 +446,6 @@ fn every_supported_module_rejects_bogus_call() { const SKIP: &[&str] = &[ // Side-effect-only — no value binding to access. "dotenv/config", - // External (non-bundled) bindings — out-of-tree as of v0.5.557. - "tursodb", - "iroh", ]; let mut failures: Vec = Vec::new(); diff --git a/crates/perry/src/commands/compile/optimized_libs/freshness.rs b/crates/perry/src/commands/compile/optimized_libs/freshness.rs index b2e25ccde3..8aab6c74c7 100644 --- a/crates/perry/src/commands/compile/optimized_libs/freshness.rs +++ b/crates/perry/src/commands/compile/optimized_libs/freshness.rs @@ -749,7 +749,6 @@ pub(crate) fn binding_needs_shared_tokio(module: &str) -> bool { // HTTP clients (reqwest, hyper) | "axios" | "node-fetch" - | "fetch" // undici — glue over the native fetch stack (network I/O family). // The wrapper itself has no tokio dep today, but it rides the // shared build so the driver auto-builds its archive alongside diff --git a/crates/perry/src/commands/stdlib_features.rs b/crates/perry/src/commands/stdlib_features.rs index bc51e18251..a7f4b0561b 100644 --- a/crates/perry/src/commands/stdlib_features.rs +++ b/crates/perry/src/commands/stdlib_features.rs @@ -81,16 +81,6 @@ pub fn module_to_features(module: &str) -> &'static [&'static str] { // `database-sqlite` feature with better-sqlite3 — DatabaseSync / // StatementSync route to the same `js_sqlite_*` runtime. "sqlite" | "bun:sqlite" => &["database-sqlite"], - // tursodb (#424) lives in the external - // `PerryTS/tursodb-bindings` repo (`bun add @perryts/tursodb`) - // since v0.5.557 — perry's package.json `perry.nativeLibrary` - // resolution path picks it up from `node_modules/`. No - // perry-stdlib feature gate to manage. - "tursodb" => &[], - // iroh (#425) lives in the external `PerryTS/iroh-bindings` - // repo (`bun add @perryts/iroh`) since v0.5.557 — same model - // as tursodb above. - "iroh" => &[], // Redis is detected via the ioredis class name in collect_modules, // but if it shows up as an explicit import we still need the feature. // `database-redis` umbrella retained for backwards-compat; diff --git a/crates/perry/well_known_bindings.toml b/crates/perry/well_known_bindings.toml index b72de46d51..59e13d4598 100644 --- a/crates/perry/well_known_bindings.toml +++ b/crates/perry/well_known_bindings.toml @@ -511,14 +511,6 @@ repo = "https://github.com/node-fetch/node-fetch" ref = "8b3320d2a7c07bce4afc6b2bf6c3bbddda85b01f" ported-at = "3.3.2" date = "2026-07-30" -[bindings.fetch] -crate = "perry-ext-fetch" -lib = "perry_ext_fetch" -tracking = "#466" -# Bare `fetch` is an alias for the node-fetch surface (same wrapper crate); it -# is not itself an npm package, so it inherits node-fetch's provenance. -alias-of = "node-fetch" - [bindings.ws] crate = "perry-ext-ws" lib = "perry_ext_ws" diff --git a/docs/api/perry.d.ts b/docs/api/perry.d.ts index cb700c98cd..87dc9693bb 100644 --- a/docs/api/perry.d.ts +++ b/docs/api/perry.d.ts @@ -1,6 +1,6 @@ // Auto-generated from Perry's API manifest (#465). Do not edit by hand. // Source: perry-api-manifest::API_MANIFEST -// Coverage: 2095 entries across 138 modules +// Coverage: 2093 entries across 136 modules type PerryI8 = number & { readonly __perryI8?: never }; type PerryI16 = number & { readonly __perryI16?: never }; @@ -2096,11 +2096,6 @@ declare module "iovalkey" { export function createClient(...args: any[]): any; } -declare module "iroh" { - /** stdlib */ - export function bind(...args: any[]): any; -} - declare module "jsonwebtoken" { /** stdlib */ export function decode(token: string): any; @@ -4141,11 +4136,6 @@ declare module "tty" { export function isatty(...args: any[]): any; } -declare module "tursodb" { - /** stdlib */ - export function open(...args: any[]): any; -} - declare module "typescript" { /** stdlib */ export const DiagnosticCategory: any; diff --git a/docs/src/api/reference.md b/docs/src/api/reference.md index 457840e2d4..afcbe5c54a 100644 --- a/docs/src/api/reference.md +++ b/docs/src/api/reference.md @@ -2,7 +2,7 @@ This page is auto-generated from Perry's compile-time API manifest (`perry-api-manifest::API_MANIFEST`). It is the source of truth for what `perry compile` accepts; references to symbols not listed here produce `R005 UnimplementedApi` (issue #463). Stubs (#464) are flagged ⚠ — they link cleanly but no-op at runtime on the chosen target. -Total: 3054 entries across 140 modules. +Total: 3035 entries across 138 modules. ## Modules @@ -64,7 +64,6 @@ Total: 3054 entries across 140 modules. - [`inspector/promises`](#inspectorpromises) - [`ioredis`](#ioredis) - [`iovalkey`](#iovalkey) -- [`iroh`](#iroh) - [`jsonwebtoken`](#jsonwebtoken) - [`lodash`](#lodash) - [`lru-cache`](#lru-cache) @@ -132,7 +131,6 @@ Total: 3054 entries across 140 modules. - [`timers/promises`](#timerspromises) - [`tls`](#tls) - [`tty`](#tty) -- [`tursodb`](#tursodb) - [`typescript`](#typescript) - [`undici`](#undici) - [`url`](#url) @@ -2014,22 +2012,6 @@ Total: 3054 entries across 140 modules. - `createClient` — module -## `iroh` - -### Methods - -- `acceptBi` — instance -- `acceptOne` — instance -- `bind` — module -- `close` — instance -- `connClose` — instance -- `connect` — instance -- `nodeId` — instance -- `openBi` — instance -- `streamFinish` — instance -- `streamReadToEnd` — instance -- `streamWrite` — instance - ## `jsonwebtoken` ### Methods @@ -3786,19 +3768,6 @@ Total: 3054 entries across 140 modules. - `removeListener` — instance *(class: `WriteStream`)* - `setRawMode` — instance *(class: `ReadStream`)* -## `tursodb` - -### Methods - -- `close` — instance -- `exec` — instance -- `execBatch` — instance -- `isAutocommit` — instance -- `lastInsertRowid` — instance -- `open` — module -- `queryAll` — instance -- `queryOne` — instance - ## `typescript` ### Methods diff --git a/docs/src/native-libraries/governance.md b/docs/src/native-libraries/governance.md index dd9a302695..1591f27649 100644 --- a/docs/src/native-libraries/governance.md +++ b/docs/src/native-libraries/governance.md @@ -99,7 +99,7 @@ from `well_known_bindings.toml`. Regenerate this table with | `perry-ext-events` | `events` | Runtime API | Keep near core; consolidate when practical | Bundled; retained | | `perry-ext-exponential-backoff` | `exponential-backoff` | Source package | Compile the upstream package source | Bundled; migration pending | | `perry-ext-fastify` | `fastify` | Source package | Compile the upstream package source | Bundled; migration pending | -| `perry-ext-fetch` | `fetch`
`node-fetch` | Source package | Compile the upstream package source | Bundled; migration pending | +| `perry-ext-fetch` | `node-fetch` | Source package | Compile the upstream package source | Bundled; migration pending | | `perry-ext-http` | `http`
`http2`
`https` | Runtime API | Keep near core; consolidate when practical | Bundled; retained | | `perry-ext-ioredis` | `ioredis`
`iovalkey`
`redis` | Source package | Compile the upstream package source | Bundled; migration pending | | `perry-ext-jsonwebtoken` | `jsonwebtoken` | Source package | Compile the upstream package source | Bundled; migration pending |