Skip to content

Native-module namespaces don't enumerate exports — turbopack/Babel wildcard interop yields empty namespace (breaks Auth.js login via jose HKDF) #6667

Description

@proggeramlug

Summary

Perry's native-module namespace objects (NATIVE_MODULE_CLASS_ID) do not enumerate their exports:

const crypto = require("crypto");
Object.keys(crypto).length; // node: 70   perry: 1
let n = 0; for (const k in crypto) n++;  // node: 70   perry: 0
({ ...crypto }).createHmac;  // node: [Function]   perry: undefined

Every interop layer that builds a namespace by enumeration therefore produces an empty namespace: turbopack's ESM-import interop over an externalized builtin (e.i(...) on a.x("crypto", () => require("crypto"))), Babel's interopRequireWildcard, and plain object spread.

Production impact (how this was found): Auth.js credentials login on a Next.js 16 App Router standalone fails with CallbackRouteError: TypeError: value is not a function on the SUCCESS path only. jose's compiled HKDF does Z = e.i(<crypto>), probes typeof Z.hkdf (undefined → picks its pure-JS fallback), and the fallback calls (0, Z.createHmac)(...) — also undefined through the empty interop namespace → the session-token derivation throws, so every successful password check still 302s to error=Configuration. Failed logins work (never reach HKDF), which masked this until a real credentials round-trip.

Z.default.randomBytes style access (interop default member) works — only named enumeration/copy is missing.

Suggested direction

Give enumeration surfaces (Object.keys/getOwnPropertyNames, for-in, object spread/Object.assign copy) a native-module arm that synthesizes the export-name list per module and, for copies, materializes bound_native_callable_export_value(module, name) per key. A partial inventory already exists as the (module, method) → arity tables in object/native_module/callable_exports.rs; a fuller per-module export inventory (constants/objects included) would close the node gap (crypto = 70 keys in Node 22).

Repro: the snippet above; observed on main @ 5eb2bc4, macOS arm64.

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