SIGN IN SIGN UP
denoland / deno UNCLAIMED

A modern runtime for JavaScript and TypeScript.

0 0 16 Rust

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