{"id":16348,"library":"emnapi","title":"emnapi: Node-API for WebAssembly","description":"emnapi provides a robust implementation of Node-API (N-API) tailored for Emscripten, WASI-SDK, and clang with WebAssembly support. Its primary goal is to enable developers to port existing Node-API native addons to WebAssembly with minimal code modifications, striving to ensure runtime behavior closely matches native Node.js environments. The library is actively developed, with its current stable version being v1.10.0, released through a consistent cadence of frequent updates addressing bug fixes and new Node-API features. A key differentiator is its role in powering WebAssembly capabilities for projects like napi-rs and enabling Node.js native addons within environments like StackBlitz's WebContainer. It aims to synchronize Node-API changes from the upstream Node.js project, ensuring compatibility and feature parity.","status":"active","version":"1.10.0","language":"javascript","source_language":"en","source_url":"https://github.com/toyobayashi/emnapi","tags":["javascript","emscripten","wasm","emcc","webassembly","binding","clang","c","c++","typescript"],"install":[{"cmd":"npm install emnapi","lang":"bash","label":"npm"},{"cmd":"yarn add emnapi","lang":"bash","label":"yarn"},{"cmd":"pnpm add emnapi","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for C++ Node-API development, providing convenient C++ wrappers for N-API.","package":"node-addon-api","optional":true},{"reason":"Required at runtime in JavaScript environments to load and interact with emnapi-compiled WebAssembly modules, especially when using Emscripten.","package":"@emnapi/runtime","optional":false},{"reason":"An alternative runtime for non-Emscripten WASM environments where Node-API is needed.","package":"@emnapi/core","optional":true}],"imports":[{"note":"This function retrieves the emnapi N-API runtime object, essential for WebAssembly module instantiation. The `emnapi` package itself is often a dev/build dependency, while `@emnapi/runtime` is the primary JavaScript runtime dependency for client-side usage.","wrong":"const { getNapiRuntime } = require('emnapi');","symbol":"getNapiRuntime","correct":"import { getNapiRuntime } from 'emnapi';"},{"note":"Provides the low-level Emscripten N-API context. Direct interaction is typically for advanced use cases or debugging.","wrong":"const emnapiCtx = require('emnapi').emnapiCtx;","symbol":"emnapiCtx","correct":"import { emnapiCtx } from 'emnapi';"},{"note":"Used for type hinting the return value of `getNapiRuntime` or other emnapi-related objects in TypeScript projects, ensuring type safety without importing a value at runtime.","wrong":"import { NapiRuntime } from 'emnapi';","symbol":"NapiRuntime","correct":"import type { NapiRuntime } from 'emnapi';"}],"quickstart":{"code":"import { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { getNapiRuntime } from 'emnapi';\n\n// In a CommonJS environment, replace 'import.meta.url' with '__filename' and 'dirname(fileURLToPath(...))' with '__dirname'.\nconst currentModuleDir = typeof __dirname !== 'undefined' ? __dirname : dirname(fileURLToPath(import.meta.url));\n\n// Assuming 'hello.wasm' is compiled from C/C++ using emnapi and placed next to this script.\nconst wasmPath = join(currentModuleDir, './hello.wasm');\nconst wasmBytes = readFileSync(wasmPath);\n\nasync function runWasmModule() {\n  try {\n    // Initialize the emnapi runtime for the WebAssembly instance\n    const napi = getNapiRuntime();\n\n    // Instantiate the WebAssembly module with the emnapi imports\n    // The 'napi' object is crucial for providing the N-API environment to the WASM module.\n    const { instance } = await WebAssembly.instantiate(wasmBytes, { napi });\n\n    // Access exported functions from the WASM module\n    // For a simple 'hello world' N-API module compiled with emnapi, it might expose a function like 'hello'.\n    // The exact function name depends on your C/C++ N-API addon's exports.\n    const helloFunction = instance.exports.hello; // Replace 'hello' with your actual exported function name\n\n    if (typeof helloFunction === 'function') {\n      const result = helloFunction();\n      console.log('Result from WASM module:', result); // Expected output might be 'world' or similar\n    } else {\n      console.error('The exported function \"hello\" was not found or is not a function in the WASM module.');\n    }\n  } catch (err) {\n    console.error('Failed to load or run WASM module with emnapi:', err);\n  }\n}\n\nrunWasmModule();","lang":"typescript","description":"This quickstart demonstrates how to load a WebAssembly module (e.g., `hello.wasm`) compiled with emnapi, instantiate it in a Node.js environment using the `emnapi` runtime, and invoke an exported function from JavaScript/TypeScript."},"warnings":[{"fix":"Applications must now explicitly manage WebAssembly memory growth or pre-allocate sufficient memory. Do not depend on `napi_adjust_external_memory` for memory expansion; it is solely for notifying the runtime about external memory usage.","message":"As of v1.10.0, the `napi_adjust_external_memory` function no longer attempts to grow WebAssembly memory. If your application previously relied on this function to expand WASM memory, it will now fail to do so, potentially causing memory allocation errors.","severity":"breaking","affected_versions":">=1.10.0"},{"fix":"Ensure that `npm install @emnapi/runtime` (or `@emnapi/core`) is explicitly added to your project's dependencies alongside `emnapi` itself.","message":"The `emnapi` npm package serves primarily as a development and build-time dependency. To actually execute emnapi-compiled WebAssembly modules in a JavaScript runtime, you *must* also install either `@emnapi/runtime` (for Emscripten-based builds) or `@emnapi/core` (for non-Emscripten WASM environments) as a separate runtime dependency. Failing to do so will result in module loading failures at runtime.","severity":"gotcha","affected_versions":"all"},{"fix":"It is critical to upgrade to emnapi v1.9.0 or any later version to mitigate these severe concurrency bugs and ensure the stability and correctness of `napi_threadsafe_function` usage.","message":"Versions of emnapi prior to v1.9.0 contained known data race and use-after-free vulnerabilities within its `napi_threadsafe_function` implementation. These issues could lead to unpredictable behavior, crashes, or incorrect results, particularly in multi-threaded WebAssembly scenarios.","severity":"gotcha","affected_versions":"<1.9.0"},{"fix":"Always consult the official emnapi documentation's 'Prerequisites' section to confirm your development environment meets all specified version requirements for Node.js, npm, and Emscripten/WASI SDK.","message":"emnapi requires specific versions of its prerequisites, including Node.js (>= v16.15.0), npm (>= v8), and Emscripten (>= v3.1.9) or compatible WASI SDK/LLVM clang versions. Using outdated or incompatible versions can lead to build failures, unexpected runtime errors, or incorrect behavior.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Run `npm install @emnapi/runtime` to add the required runtime dependency to your project's `node_modules`.","cause":"The `@emnapi/runtime` package, which provides the necessary JavaScript glue code for emnapi-compiled WASM modules, has not been installed or is not resolvable.","error":"Error: Cannot find module '@emnapi/runtime'"},{"fix":"Ensure you correctly pass the `napi` object as an import, for example: `await WebAssembly.instantiate(wasmBytes, { napi: getNapiRuntime() });`","cause":"The import object provided to `WebAssembly.instantiate` is missing the `napi` property, or the value for `napi` is not the object returned by `getNapiRuntime()`.","error":"WebAssembly.instantiate(): Imports argument must be an object"},{"fix":"In your C/C++ code, explicitly manage WebAssembly memory growth or ensure the initial memory allocation (`-s INITIAL_MEMORY=...`) is sufficient for your application's needs, especially for versions `1.10.0` and above.","cause":"With emnapi v1.10.0+, `napi_adjust_external_memory` no longer extends WebAssembly memory. Attempts to rely on it for growth will fail silently or result in memory exhaustion if the module needs more memory than initially allocated.","error":"WASM memory allocation failed during napi_adjust_external_memory (or similar memory errors)"}],"ecosystem":"npm"}