Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions changelog.d/10618-tier-a-native-binding-removal.md
Original file line number Diff line number Diff line change
@@ -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.
11 changes: 6 additions & 5 deletions crates/perry-api-manifest/src/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -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
Expand Down
29 changes: 0 additions & 29 deletions crates/perry-api-manifest/src/entries/part_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
12 changes: 0 additions & 12 deletions crates/perry-hir/tests/unimplemented_api_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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/<pkg>/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<String> = Vec::new();
Expand Down Expand Up @@ -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<String> = Vec::new();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 0 additions & 10 deletions crates/perry/src/commands/stdlib_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 0 additions & 8 deletions crates/perry/well_known_bindings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 1 addition & 11 deletions docs/api/perry.d.ts
Original file line number Diff line number Diff line change
@@ -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 };
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
33 changes: 1 addition & 32 deletions docs/src/api/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion docs/src/native-libraries/governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`<br>`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`<br>`http2`<br>`https` | Runtime API | Keep near core; consolidate when practical | Bundled; retained |
| `perry-ext-ioredis` | `ioredis`<br>`iovalkey`<br>`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 |
Expand Down
Loading