~14 min read • Updated Dec 26, 2025
1. Features of Node-API
- All Node-API calls return a status code of type
napi_status. - JavaScript values are abstracted behind the opaque type
napi_value. - Error details can be retrieved using
napi_get_last_error_info.
2. Writing Addons in Different Languages
Node-API is a C-based API that guarantees ABI stability. This allows Addons to be written in other programming languages. The node-addon-api library provides a C++ wrapper for easier development.
// node-addon-api Object obj = Object::New(env); obj["foo"] = String::New(env, "bar");
3. ABI Stability
To remain ABI-compatible across Node.js versions, Addons must use #include <node_api.h>. Other APIs such as V8 or libuv do not provide ABI stability guarantees.
4. Enums in Node-API
All enums are treated as int32_t. New values may be added without removal or renaming, so code should always handle unknown values safely.
5. Build Tools
- node-gyp: Traditional build system bundled with npm, based on GYP.
- CMake.js: Alternative build system for projects already using CMake.
6. Precompiled Binaries
- node-pre-gyp: Supports uploading binaries to servers, especially Amazon S3.
- prebuild: Uploads binaries to GitHub releases.
- prebuildify: Bundles binaries with npm packages for immediate availability.
7. Node-API Versions
From version 9 onward, Node-API versions are additive but may require updates for newer versions. By default, Node.js provides version 8 unless #define NAPI_VERSION is specified.
| Node-API Version | Supported In |
|---|---|
| 10 | v22.14.0+, v23.6.0+ |
| 9 | v18.17.0+, v20.3.0+, v21.0.0+ |
| 8 | v12.22.0+, v14.17.0+, v15.12.0+, v16.0.0+ |
| 7 | v10.23.0+, v12.19.0+, v14.12.0+, v15.0.0+ |
8. Separating Node.js-Specific Code
Node.js-specific entry points can be separated from the core functionality, allowing the same code to compile against other Node-API implementations.
// addon.h #includenapi_value create_addon(napi_env env);
Conclusion
Node-API provides a stable, engine-independent layer for building native Addons in Node.js. By ensuring ABI stability, developers can create modules that continue to work across Node.js versions without recompilation, making Addon development more robust and future-proof.
1. Managing Environment Data
napi_set_instance_data: Associates data with the current environment, tied to its life cycle.napi_get_instance_data: Retrieves data previously associated with the environment.
// Example napi_set_instance_data(env, data, finalize_cb, NULL); napi_get_instance_data(env, &retrievedData);
2. Basic Node-API Data Types
napi_status: Indicates success or failure of an API call.napi_extended_error_info: Provides detailed error information including message and code.napi_env: Represents the environment context for Node-API calls.napi_value: Opaque pointer representing a JavaScript value.
3. Thread-Safe Functions
napi_threadsafe_function allows JavaScript functions to be called safely from multiple threads.
napi_tsfn_release/napi_tsfn_abort: Modes for releasing or closing thread-safe functions.napi_tsfn_nonblocking/napi_tsfn_blocking: Modes for handling queue behavior when full.
4. Object Lifetime Management
napi_handle_scope: Controls the lifetime of objects created within a scope.napi_escapable_handle_scope: Allows values created in a scope to escape to a parent scope.napi_ref: Manages references to JavaScript values and their lifetimes.napi_type_tag: Tags objects with a UUID to ensure type safety.
5. Cleanup Hooks
napi_async_cleanup_hook_handle manages asynchronous cleanup events and must be released when cleanup is complete.
6. Callback Types
napi_callback_info: Provides context information when a callback is invoked.napi_callback: Standard function signature for native functions exposed to JavaScript.
typedef napi_value (*napi_callback)(napi_env, napi_callback_info);
Conclusion
Environment Life Cycle APIs in Node.js enable safe management of data, objects, and functions across multiple environments and threads. These APIs are essential for native Addons that need to interact with multiple contexts, ensuring proper control of object lifetimes and environment-specific data.
1. Finalizers in Node-API
node_api_basic_finalize: Called when objects with external data are garbage-collected. Only APIs that acceptnode_api_basic_envcan be used here.napi_finalize: Used to schedule Node-API calls after a garbage collection cycle has completed.
2. Asynchronous Callbacks
napi_async_execute_callback: Executes asynchronous operations without interacting directly with JavaScript.napi_async_complete_callback: Completes asynchronous operations and interacts with JavaScript safely.napi_threadsafe_function_call_js: Safely invokes JavaScript functions from secondary threads.
3. Cleanup Hooks
napi_cleanup_hook: Called when the environment is being torn down.napi_async_cleanup_hook: Initiates asynchronous cleanup actions during environment teardown.
4. Error Handling with Node-API
All Node-API functions return a napi_status value:
napi_ok: Success.napi_pending_exception: A JavaScript exception is pending.- Other values indicate specific errors.
Detailed error information can be retrieved using napi_get_last_error_info, which returns a napi_extended_error_info structure containing the error message and code.
5. Exception Management
napi_throw: Throws a JavaScript value as an exception.napi_throw_error: Creates and throws a JavaScriptErrorwith a message.napi_throw_type_error: Throws aTypeError.napi_throw_range_error: Throws aRangeError.node_api_throw_syntax_error: Throws aSyntaxError.
Utility functions such as napi_create_error and napi_create_type_error allow developers to construct error objects programmatically.
Conclusion
Finalizers and error handling in Node-API are essential for managing resources and ensuring safe interaction between native code and JavaScript. By using these APIs correctly, developers can build stable, secure, and forward-compatible native Addons for Node.js.
1. Creating Errors in Node-API
napi_create_range_error: Creates a JavaScriptRangeErrorwith the provided message.node_api_create_syntax_error: Creates a JavaScriptSyntaxErrorwith the provided message.
// Example napi_value error; napi_create_range_error(env, NULL, msg, &error);
2. Exception Management
napi_get_and_clear_last_exception: Retrieves and clears the last pending exception.napi_is_exception_pending: Checks if an exception is currently pending.napi_fatal_exception: Triggers an uncaught exception in JavaScript.napi_fatal_error: Terminates the process immediately in case of unrecoverable errors.
3. Object Lifetime Management
Handles returned by Node-API must be managed carefully to prevent premature garbage collection or memory leaks.
napi_open_handle_scope/napi_close_handle_scope: Open and close scopes to control handle lifetimes.napi_open_escapable_handle_scope: Allows one handle to escape to an outer scope.napi_escape_handle: Promotes a handle to be valid in the parent scope.
4. Persistent References
napi_create_reference: Creates a persistent reference with an initial reference count.napi_delete_reference: Deletes a reference, allowing the object to be garbage-collected.napi_reference_ref: Increments the reference count for a persistent reference.
Persistent references are essential when objects need to remain alive across multiple native method calls. Proper management prevents memory leaks and ensures safe cleanup.
Conclusion
By using napi_create_range_error and other error-handling APIs, developers can safely generate JavaScript errors from native code. Combined with handle scopes and persistent references, Node-API provides a robust framework for managing object lifetimes and ensuring memory safety in native Addons.
1. Managing References
napi_reference_unref: Decrements the reference count of anapi_refand returns the new count.napi_get_reference_value: Retrieves the JavaScript value associated with anapi_ref, orNULLif invalid.
2. Cleanup Hooks
To free resources when a Node.js environment exits, developers can register cleanup hooks:
napi_add_env_cleanup_hook: Registers a cleanup function to run at environment teardown.napi_remove_env_cleanup_hook: Removes a previously registered cleanup hook.napi_add_async_cleanup_hook: Registers an asynchronous cleanup hook.napi_remove_async_cleanup_hook: Removes an asynchronous cleanup hook.
3. Finalization During Environment Exit
When the Node.js environment is torn down, all napi_finalize callbacks for objects, thread-safe functions, and instance data are invoked. To avoid use-after-free issues, addons should register cleanup hooks to release resources in the correct order.
4. Module Registration
Node-API modules are registered using macros:
NAPI_MODULE: Registers an Init function as the entry point.NAPI_MODULE_INIT: A shorthand for defining Init functions.
// Example Init
napi_value Init(napi_env env, napi_value exports) {
napi_value answer;
napi_create_int64(env, 42, &answer);
napi_set_named_property(env, exports, "answer", answer);
return exports;
}
5. Working with JavaScript Values
Node-API exposes functions to create and manipulate JavaScript values:
napi_create_array: Creates a JavaScript Array.napi_create_buffer: Creates a Node.js Buffer.napi_create_date: Creates a JavaScript Date object.
Conclusion
By using napi_reference_unref and cleanup hooks, developers can manage resources safely and prevent memory leaks in native Addons. Combined with APIs for creating JavaScript values, Node-API provides a powerful framework for building stable and efficient native modules in Node.js.
1. External Values
napi_create_external: Creates a JavaScript value with attached external data. This value is of typenapi_externaland does not support additional properties.napi_create_external_arraybuffer: Creates anArrayBufferbacked by externally allocated memory.napi_create_external_buffer: Creates aBufferbacked by external memory.
All of these APIs support an optional finalize_cb callback, which is invoked when the JavaScript object is garbage-collected, allowing safe cleanup of external resources.
2. Object Creation
napi_create_object: Creates a default JavaScript object (equivalent tonew Object()).napi_create_object_with_properties: Creates an object with a specified prototype and properties in one atomic operation, improving efficiency.
3. Symbols
napi_create_symbol: Creates a new JavaScript Symbol with an optional description.node_api_symbol_for: Retrieves or creates a Symbol in the global registry, ensuring reuse across modules.
4. Typed Arrays and DataView
napi_create_typedarray: Creates a TypedArray over an existing ArrayBuffer.napi_create_dataview: Creates a DataView for flexible access to binary data in an ArrayBuffer.
5. Buffer from ArrayBuffer
node_api_create_buffer_from_arraybuffer creates a Node.js Buffer object from an existing ArrayBuffer, enabling direct binary data manipulation in JavaScript.
6. Converting C Types to JavaScript
napi_create_int32: Converts a Cint32_tto a JavaScript number.napi_create_uint32: Converts a Cuint32_tto a JavaScript number.napi_create_int64: Converts a Cint64_tto a JavaScript number (with precision limits).napi_create_double: Converts a Cdoubleto a JavaScript number.
Conclusion
By using napi_create_external and related object creation APIs, developers can safely integrate native memory and structures into JavaScript. These functions provide a powerful toolkit for building efficient, stable, and memory-safe native Addons in Node.js.
1. BigInt Creation
napi_create_bigint_int64: Converts a Cint64_tinto a JavaScript BigInt.napi_create_bigint_uint64: Converts a Cuint64_tinto a JavaScript BigInt.napi_create_bigint_words: Creates a BigInt from an array of 64-bit words, supporting very large integers.
2. String Creation
napi_create_string_latin1: Creates a JavaScript string from a Latin1-encoded C buffer.napi_create_string_utf16: Creates a JavaScript string from a UTF-16 encoded C buffer.napi_create_string_utf8: Creates a JavaScript string from a UTF-8 encoded C buffer.node_api_create_external_string_latin1/node_api_create_external_string_utf16: Creates external strings backed by native memory, with optional finalizers for cleanup.
3. Optimized Property Keys
node_api_create_property_key_latin1: Creates an optimized property key string using Latin1 encoding.node_api_create_property_key_utf16: Creates an optimized property key string using UTF-16 encoding.node_api_create_property_key_utf8: Creates an optimized property key string using UTF-8 encoding.
These optimized keys improve performance in JavaScript engines by enabling faster property lookups.
4. Array and Buffer Info
napi_get_array_length: Retrieves the length of a JavaScript array.napi_get_arraybuffer_info: Retrieves the underlying buffer and length of an ArrayBuffer.napi_get_buffer_info: Retrieves the underlying buffer and length of a Node.js Buffer or Uint8Array.
5. TypedArray and DataView Info
napi_get_typedarray_info: Retrieves type, length, and buffer details of a TypedArray.napi_get_dataview_info: Retrieves length and buffer details of a DataView.
Conclusion
APIs such as napi_create_bigint and napi_create_string, combined with property key and buffer information functions, provide a powerful toolkit for integrating native data with JavaScript. These capabilities allow developers to build Addons that handle large integers, multiple text encodings, and efficient property access while maintaining memory safety and performance.
1. TypedArray and DataView Information
napi_get_typedarray_info: Retrieves type, length, buffer, and byte offset of a TypedArray.napi_get_dataview_info: Retrieves length, buffer, and byte offset of a DataView.
2. Date and Primitive Values
napi_get_date_value: Returns the time value of a JavaScript Date as a C double.napi_get_value_bool: Converts a JavaScript Boolean to a C bool.napi_get_value_double: Converts a JavaScript Number to a C double.napi_get_value_int32,napi_get_value_int64,napi_get_value_uint32: Convert JavaScript Numbers to C integer types.
3. BigInt Values
napi_get_value_bigint_int64: Converts a BigInt to a C int64_t, with lossless flag.napi_get_value_bigint_uint64: Converts a BigInt to a C uint64_t, with lossless flag.napi_get_value_bigint_words: Converts a BigInt into sign bit and array of 64-bit words.
4. Strings and External Values
napi_get_value_string_latin1: Retrieves a Latin1-encoded string.napi_get_value_string_utf8: Retrieves a UTF-8 string.napi_get_value_string_utf16: Retrieves a UTF-16 string.napi_get_value_external: Retrieves external data pointer from a JavaScript external value.
5. Global Instances
napi_get_boolean: Returns the JavaScript Boolean singleton.napi_get_global: Returns the global object.napi_get_null: Returns the JavaScript null object.napi_get_undefined: Returns the JavaScript undefined value.
6. Abstract Operations
napi_coerce_to_bool: Coerces a value to Boolean.napi_coerce_to_number: Coerces a value to Number.napi_coerce_to_object: Coerces a value to Object.napi_coerce_to_string: Coerces a value to String.
7. Type Checking and Equality
napi_typeof: Returns the type of a JavaScript value.napi_instanceof: Checks if an object is an instance of a constructor.napi_is_array,napi_is_arraybuffer,napi_is_buffer,napi_is_date,napi_is_error,napi_is_typedarray,napi_is_dataview: Type checks for specific JavaScript objects.napi_strict_equals: Performs strict equality comparison.
8. ArrayBuffer Management
napi_detach_arraybuffer: Detaches an ArrayBuffer.napi_is_detached_arraybuffer: Checks if an ArrayBuffer is detached.node_api_is_sharedarraybuffer: Checks if a value is a SharedArrayBuffer.
Conclusion
APIs such as napi_get_typedarray_info, napi_get_value_string_utf8, and napi_get_value_bigint_int64 provide native Addons with safe and efficient access to JavaScript values. By combining type checks, coercion functions, and buffer management, Node-API ensures that native code can interact with JavaScript objects in a way that is consistent, memory-safe, and aligned with ECMAScript semantics.
1. SharedArrayBuffer Creation
node_api_create_sharedarraybuffer: Creates a SharedArrayBuffer with a specified length. This buffer can be shared across multiple workers.- The underlying data buffer can optionally be returned to native code for direct manipulation.
2. Property Management
Node-API allows property management similar to JavaScript:
napi_set_property/napi_get_property: Set or retrieve a property by key.napi_set_named_property/napi_get_named_property: Manage properties by string name.napi_set_element/napi_get_element: Manage properties by numeric index (like arrays).napi_define_properties: Efficiently define multiple properties usingnapi_property_descriptor.
3. Property Attributes
napi_writable: Property is writable.napi_enumerable: Property is enumerable.napi_configurable: Property is configurable.napi_static: Defines static properties in classes.
4. Object Freezing and Sealing
napi_object_freeze: Prevents adding or modifying properties.napi_object_seal: Prevents adding new properties and marks existing ones as non-configurable.
5. JavaScript Functions
napi_create_function: Creates a JavaScript function from native code.napi_call_function: Calls a JavaScript function from native code.napi_get_cb_info: Retrieves callback information such as arguments andthis.napi_get_new_target: Retrievesnew.targetin constructor calls.napi_new_instance: Instantiates a new object using a constructor function.
Conclusion
By using node_api_create_sharedarraybuffer along with property and function management APIs, developers can build powerful native Addons that share data across workers and fully interact with JavaScript objects and functions. These APIs ensure efficient memory handling and seamless integration between native and JavaScript code.
1. Post Finalizer
node_api_post_finalizer: Schedules anapi_finalizecallback asynchronously in the event loop.- This allows cleanup operations requiring Node-API calls to run safely outside of GC finalization.
2. Simple Asynchronous Work
napi_create_async_work: Creates an async work object with execute and complete callbacks.napi_queue_async_work: Queues async work for execution.napi_cancel_async_work: Cancels queued work before execution begins.napi_delete_async_work: Frees resources associated with async work.
3. Custom Asynchronous Operations
napi_async_init: Initializes an async context for tracking operations.napi_async_destroy: Destroys an async context to prevent leaks.napi_make_callback: Calls a JavaScript function after an async operation completes.napi_open_callback_scope/napi_close_callback_scope: Manage callback scopes for safe execution.
4. Version and Memory Management
napi_get_node_version: Retrieves Node.js version information.napi_get_version: Returns the highest supported Node-API version.napi_adjust_external_memory: Adjusts the amount of externally allocated memory tracked by JavaScript objects.
5. Promises
napi_create_promise: Creates a Promise and its associated deferred object.napi_resolve_deferred: Resolves a Promise with a given value.napi_reject_deferred: Rejects a Promise with a given value.napi_is_promise: Checks if a value is a native Promise object.
6. Script Execution
napi_run_script: Executes a JavaScript string in the global scope.
7. Event Loop Access
napi_get_uv_event_loop: Retrieves the current libuv event loop instance.
8. Thread-Safe Function Calls
napi_create_threadsafe_function: Creates a thread-safe function callable from multiple threads.napi_call_threadsafe_function: Queues data for invoking a JavaScript function.napi_release_threadsafe_function: Releases resources associated with a thread-safe function.
Conclusion
node_api_post_finalizer and the asynchronous APIs in Node-API are essential for building robust native Addons. They enable safe cleanup, efficient async work scheduling, promise handling, and thread-safe communication between native threads and JavaScript, ensuring stability and performance in complex applications.
Written & researched by Dr. Shahin Siami