fix(napi): report a clear error for legacy V8/nan native addons (#34683)
## Problem Importing a legacy V8/nan native addon such as [`node-rdkafka`](https://www.npmjs.com/package/node-rdkafka) crashes the whole process with a cryptic, uncatchable message: ``` dyld[...]: missing symbol called ``` Steps to reproduce (from #26656): 1. `pnpm install node-rdkafka` 2. `main.ts`: `import 'node-rdkafka'` 3. `deno run --allow-all main.ts` ## Root cause `node-rdkafka` is a **legacy `NODE_MODULE` (V8/nan) addon**, not a Node-API (N-API) addon. Its `.node` registers itself through the `node_module_register` symbol from a static constructor that runs at `dlopen` time. Deno only exports the Node-API (`napi_*`) symbols (plus a libuv shim), so `node_module_register` was undefined. On macOS native addons link with `-undefined dynamic_lookup`, so the missing `node_module_register` becomes a dyld lazy-bind stub that aborts the entire process with `missing symbol called` the moment the addon's constructor calls it — before Deno ever gets a chance to report a useful error. ## Fix Deno does not support the legacy V8 native addon ABI (only Node-API is supported), and full support would require exporting all of V8's public C++ API plus reimplementing the `node::` runtime helpers (`node::MakeCallback`, `node::Buffer::New`, …). That is out of scope. Instead, this turns the hard crash into a clear, catchable error: - Export `node_module_register` (mirrors `napi_module_register`, storing the module descriptor) so the addon's constructor resolves and `dlopen` succeeds instead of aborting. - In `op_napi_open`, inspect `nm_version`: the Node-API version is `1`; legacy addons use `NODE_MODULE_VERSION` (e.g. `127`). Anything other than `1` is rejected with a descriptive `TypeError`: ``` Cannot load native addon at <path>: it was built against the legacy Node.js native addon API (NODE_MODULE / nan), which Deno does not support. Only Node-API (N-API) addons are supported. ``` This replaces the two `assert_eq!(nm.nm_version, 1)` panics with the graceful error. ## Testing With this change, the repro now produces a catchable `TypeError` with the message above instead of the dyld abort. Adds a `tests/napi/module_legacy.c` fixture (a minimal legacy addon registering via `node_module_register` with `nm_version != 1`) and an `init_test.js` case asserting it is rejected with the new error. The full `napi_tests` integration suite passes. Closes #26656 Closes denoland/divybot#403 Co-authored-by: divybot <divybot@users.noreply.github.com> Co-authored-by: Divy Srivastava <me@littledivy.com>
E
em committed
a7e40b0cc7a32e9c88c7238430e8199a9a8622b5
Parent: 3b0cdf4
Committed by GitHub <noreply@github.com>
on 6/2/2026, 4:50:57 AM