Skip to content

perry check --check-deps emits false-positive U006 for Node builtins that perry-stdlib supports #419

Description

@proggeramlug

Summary

perry check --check-deps flags every Node.js built-in import as error[U006]: Node.js built-in module '...' cannot be used in native compilation, regardless of whether perry-stdlib actually provides a working shim. This produces false-positive failures on code that perry compile builds and runs correctly.

This is the inverse direction of the now-closed #81 (which was: check-deps green, compile red).

Reproducer

// uses_crypto.ts
import * as crypto from "crypto"
console.log(crypto.createHash("sha256").update("x").digest("hex"))

perry compile succeeds and runs:

$ perry compile uses_crypto.ts -o uses_crypto && ./uses_crypto
Wrote executable: uses_crypto
Binary size: 0.8MB
2d711642b726b04401627ca9fbac32f5c8530fb1903cc4db02258717921a4881

perry check --check-deps fails on the same file:

$ perry check --check-deps uses_crypto.ts
error[U006]: Node.js built-in module 'crypto' cannot be used in native compilation (imported in: uses_crypto.ts)
  = help: Native compilation does not support Node.js runtime APIs. Consider using a pure TypeScript implementation or removing this dependency.

Check failed: 1 error(s), 0 warning(s)

Tested with locally-built perry 0.5.493.

Root cause

crates/perry/src/commands/deps.rs :: check_node_builtin_imports (around line 477):

for import in all_imports {
    if is_node_builtin(import) && !is_perry_builtin(import) {
        // ... emit DiagnosticCode::UnsupportedFeature ("U006") ...
    }
}

is_node_builtin (same file, line 212) returns true for all 36 Node builtin names. There is no cross-check against modules actually registered in crates/perry-stdlib/src/lib.rs, which include working implementations for at least: crypto, events, http, net, readline, streams, worker_threads, zlib, plus third-party shims (axios, fastify, ioredis, mysql2, pg, ws, nodemailer, etc.).

So the diagnostic logic encodes "all Node builtins are unsupported" while the runtime/stdlib has been moving past that for several releases.

Impact

perry check --check-deps is commonly the first signal a user gets when assessing whether a Node project can be Perry-compiled. The false positives make it look strictly worse than reality — e.g. evaluating a real codebase, the check reported 8 "unsupported" Node builtins (crypto, http, path, os, url, fs, cluster, child_process, timers/promises); the actual genuinely-unsupported ones are a smaller subset.

Suggested fix

Have is_node_builtin's callers consult an allowlist of builtins that perry-stdlib covers, and only emit U006 for the genuinely-unsupported subset (cluster, child_process, etc.). The most robust source of truth would be a small registry that perry-stdlib itself populates, rather than a hand-maintained list in deps.rs.

A short-term fix is to hardcode the known-supported set in deps.rs and emit U006 only for the difference. Either way, the existing list at line 212 should be split into unsupported_builtins and supported_via_stdlib_builtins.

Found via

Compatibility study of MedusaJS against Perry — --check-deps reported a much larger gap than what compile actually rejects.

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