Env
In most cases, the Node-API is encapsulated within various high-level abstractions and structures of NAPI-RS. However, in some cases, you still need to access the underlying Node-API.
The Env struct provides access to the Node-API environment and allows you to create JavaScript values, handle errors, manage memory, and interact with the JavaScript runtime.
String and Symbol Creation
create_string
Creates a JavaScript string from a Rust type that can be converted to &str.
pub fn create_string<S: AsRef<str>>(&self, s: S) -> Result<JsString<'_>>
Example:
let js_string = env.create_string("Hello, World!")?;
create_string_from_std
Creates a JavaScript string from a Rust String.
pub fn create_string_from_std<'env>(&self, s: String) -> Result<JsString<'env>>
create_string_from_c_char
Creates a JavaScript string from a C-style string pointer. This is used for C FFI scenarios.
INFO
You can pass NAPI_AUTO_LENGTH as the len parameter if the C string is null-terminated.
pub unsafe fn create_string_from_c_char<'env>(
&self,
data_ptr: *const c_char,
len: isize,
) -> Result<JsString<'env>>
create_string_utf16
Creates a JavaScript string from UTF-16 encoded data.
pub fn create_string_utf16<C: AsRef<[u16]>>(&self, chars: C) -> Result<JsString<'_>>
create_string_latin1
Creates a JavaScript string from Latin-1 encoded data.
pub fn create_string_latin1<C: AsRef<[u8]>>(&self, chars: C) -> Result<JsString<'_>>
create_symbol
Creates a JavaScript symbol with an optional description.
pub fn create_symbol(&self, description: Option<&str>) -> Result<JsSymbol<'_>>
symbol_for
INFO
Requires napi9 feature.
Creates or retrieves a symbol from the global symbol registry.
pub fn symbol_for(&self, description: &str) -> Result<JsSymbol<'_>>
Error Handling
get_last_error_info
Retrieves extended error information about the last error that occurred.
pub fn get_last_error_info(&self) -> Result<ExtendedErrorInfo>
throw
Throws any JavaScript value as an exception.
pub fn throw<T: ToNapiValue>(&self, value: T) -> Result<()>
throw_error
Throws a JavaScript Error with the provided message and optional error code.
pub fn throw_error(&self, msg: &str, code: Option<&str>) -> Result<()>
throw_range_error
Throws a JavaScript RangeError with the provided message and optional error code.
pub fn throw_range_error(&self, msg: &str, code: Option<&str>) -> Result<()>
throw_type_error
Throws a JavaScript TypeError with the provided message and optional error code.
pub fn throw_type_error(&self, msg: &str, code: Option<&str>) -> Result<()>
throw_syntax_error requires napi9
Throws a JavaScript SyntaxError with the provided message and optional error code.
pub fn throw_syntax_error<S: AsRef<str>, C: AsRef<str>>(&self, msg: S, code: Option<C>)
fatal_error
Triggers a fatal error that immediately terminates the process.
pub fn fatal_error(self, location: &str, message: &str)
fatal_exception
INFO
Requires napi3 feature.
Triggers an 'uncaughtException' in JavaScript. Useful for async callbacks that throw unrecoverable exceptions.
pub fn fatal_exception(&self, err: Error)
create_error
Creates a JavaScript error object from a Rust Error.
pub fn create_error(&self, e: Error) -> Result<Object<'_>>
Function and Class Creation
create_function
Creates a JavaScript function from a native callback.
pub fn create_function<Args: JsValuesTupleIntoVec, Return>(
&self,
name: &str,
callback: Callback,
) -> Result<Function<'_, Args, Return>>
Example:
INFO
You can access the C Callback by adding the _c_callback suffix to the function name.
In the example below, the custom_function_c_callback is the C callback for the custom_function.
use napi::bindgen_prelude::*;
use napi_derive::napi;
#[napi]
pub fn create_function(env: &Env) -> Result<Function<u32, u32>> {
env.create_function("customFunction", custom_function_c_callback)
}
#[napi(no_export)]
fn custom_function(input: u32) -> u32 {
input * 2
}
INFO
The no_export attribute is used to prevent the function from being exported to the JavaScript side.
The custom_function is not exported, so it's not visible in the JavaScript side. But the C callback is used for creating Function in fn create_function. You can use it like this:
import { createFunction } from './index.js'
const customFunction = createFunction()
console.log(customFunction(2)) // 4
create_function_from_closure
INFO
Requires napi5 feature.
Creates a JavaScript function from a Rust closure.
pub fn create_function_from_closure<Args: JsValuesTupleIntoVec, Return, F>(
&self,
name: &str,
callback: F,
) -> Result<Function<'_, Args, Return>>
where
Return: ToNapiValue,
F: 'static + Fn(FunctionCallContext) -> Result<Return>,
Example:
use napi::bindgen_prelude::*;
use napi_derive::napi;
#[napi]
pub fn create_function(env: &Env) -> Result<Function<u32, u32>> {
let var_moved_into_closure = 42; // this variable is moved into the closure
env.create_function_from_closure("rustClosure", move |ctx| {
// get the first argument from the JavaScript side
let result = var_moved_into_closure + ctx.get::<u32>(0)?;
Ok(result)
})
}
⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
import { createFunction } from './index.js'
const rustClosure = createFunction()
console.log(rustClosure(2)) // 44
define_class
Creates a JavaScript class with the given constructor and properties.
pub fn define_class<Args: JsValuesTupleIntoVec>(
&self,
name: &str,
constructor_cb: Callback,
properties: &[Property],
) -> Result<Function<'_, Args, Unknown<'_>>>
Memory Management
adjust_external_memory
Indicates to V8 the amount of externally allocated memory kept alive by JavaScript objects.
pub fn adjust_external_memory(&self, size: i64) -> Result<i64>
run_in_scope
Executes a function within a handle scope, which helps manage memory for temporary objects.
pub fn run_in_scope<T, F>(&self, executor: F) -> Result<T>
where
F: FnOnce() -> Result<T>,
HandleScope and EscapableHandleScope
run_in_scope wraps a whole closure in one scope. When you need finer control — the classic case is a loop that creates many short-lived JavaScript values — use the standalone scope types from napi::bindgen_prelude. Without a per-iteration scope, every value created inside the loop stays alive (as a napi_handle) until the outer call returns, which can exhaust memory on large inputs.
HandleScope::create opens a scope, and the unsafe close runs your closure and then closes the scope, invalidating every value created inside it:
use napi::{bindgen_prelude::*, JsString};
#[napi]
pub fn shorter_scope(env: &Env, arr: Array) -> Result<Vec<u32>> {
let len = arr.len();
let mut result = Vec::with_capacity(len as usize);
for i in 0..len {
let scope = HandleScope::create(env)?;
let value: Unknown = arr.get_element(i)?;
let len = unsafe {
scope.close(value, |v| match v.get_type()? {
ValueType::String => {
let string = v.cast::<JsString>()?;
Ok(string.utf8_len()? as u32)
}
ValueType::Object => Ok(1),
_ => Ok(0),
})?
};
result.push(len);
}
Ok(result)
}
⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
export declare function shorterScope(arr: unknown[]): Array<number>
WARNING
close is unsafe because it invalidates every JavaScript value created
within the scope — including the one passed to the closure. Convert whatever
you need to owned Rust data (here, the u32 length) before the scope closes,
or escape the value explicitly with EscapableHandleScope.
EscapableHandleScope is for the case where one value must outlive the scope: EscapableHandleScope::with(env, args, |scope, args| ...) opens the scope, and value.escape(scope) (or scope.escape(value)) promotes a single value to the outer scope before the inner one closes when the with call returns:
use napi::{bindgen_prelude::*, JsString};
#[napi]
pub fn shorter_escapable_scope<'env>(
env: &'env Env,
create_string: Function<(), Option<JsString>>,
) -> Result<JsString<'env>> {
let mut longest_string = env.create_string("")?;
let mut prev_len = 0;
loop {
if let Some(maybe_longest) = EscapableHandleScope::with(
env,
(create_string, longest_string),
move |scope, (create_string, prev)| {
let elem = create_string.call(())?;
if let Some(string) = elem {
let len = string.utf8_len()?;
if len > prev.utf8_len()? {
return Ok(Some(Either::A(string.escape::<JsString>(scope)?)));
}
} else {
return Ok(Some(Either::B(())));
}
Ok(None)
},
)? {
match maybe_longest {
Either::A(longest) => {
if longest.utf8_len()? == prev_len {
break;
}
prev_len = longest.utf8_len()?;
longest_string = longest;
}
Either::B(_) => break,
}
}
}
Ok(longest_string)
}
Each iteration calls back into JavaScript for a candidate string; only the longest candidate escapes its iteration's scope, so the rest are released immediately instead of accumulating until the function returns.
The runnable versions of both functions live in examples/napi/src/scope.rs.
Environment Cleanup
add_env_cleanup_hook
INFO
Requires napi3 feature.
Registers a cleanup hook to be called when the environment is being torn down.
pub fn add_env_cleanup_hook<T, F>(
&self,
cleanup_data: T,
cleanup_fn: F,
) -> Result<CleanupEnvHook<T>>
where
T: 'static,
F: 'static + FnOnce(T),
remove_env_cleanup_hook
INFO
Requires napi3 feature.
Removes a previously registered cleanup hook.
pub fn remove_env_cleanup_hook<T>(&self, hook: CleanupEnvHook<T>) -> Result<()>
where
T: 'static,
add_async_cleanup_hook
INFO
Requires napi8 feature.
Registers an asynchronous cleanup hook.
pub fn add_async_cleanup_hook<Arg, F>(&self, arg: Arg, cleanup_fn: F) -> Result<()>
where
F: FnOnce(Arg),
Arg: 'static,
add_removable_async_cleanup_hook
INFO
Requires napi8 feature.
Registers a removable asynchronous cleanup hook.
pub fn add_removable_async_cleanup_hook<Arg, F>(
&self,
arg: Arg,
cleanup_fn: F,
) -> Result<AsyncCleanupHook>
where
F: FnOnce(Arg),
Arg: 'static,
Script Execution and Environment Information
run_script
Executes a JavaScript string and returns the result.
pub fn run_script<S: AsRef<str>, V: FromNapiValue>(&self, script: S) -> Result<V>
Example:
let result: i32 = env.run_script("2 + 2")?;
assert_eq!(result, 4);
get_napi_version
Gets the N-API version (process.versions.napi).
pub fn get_napi_version(&self) -> Result<u32>
get_node_version
Gets the Node.js version information.
pub fn get_node_version(&self) -> Result<NodeVersion>
get_module_file_name
INFO
Requires napi9 feature.
Retrieves the file path of the currently running JS module as a URL.
pub fn get_module_file_name(&self) -> Result<String>
get_uv_event_loop
INFO
Requires napi2 feature.
Gets a pointer to the underlying libuv event loop.
pub fn get_uv_event_loop(&self) -> Result<*mut sys::uv_loop_s>
Instance Data Management
set_instance_data
INFO
Requires napi6 feature.
Associates data with the currently running Agent.
pub fn set_instance_data<T, Hint, F>(&self, native: T, hint: Hint, finalize_cb: F) -> Result<()>
where
T: 'static,
Hint: 'static,
F: FnOnce(FinalizeContext<T, Hint>),
get_instance_data
INFO
Requires napi6 feature.
Retrieves data previously associated with the currently running Agent.
pub fn get_instance_data<T>(&self) -> Result<Option<&'static mut T>>
where
T: 'static,
Async and Future Support
spawn
Runs a task in the libuv thread pool and returns an AsyncWorkPromise.
pub fn spawn<T: 'static + Task>(&self, task: T) -> Result<AsyncWorkPromise<T::JsValue>>
spawn_future
INFO
Requires tokio_rt and napi4 feature.
Spawns a Rust future and returns a JavaScript Promise.
pub fn spawn_future<
T: 'static + Send + ToNapiValue,
F: 'static + Send + Future<Output = Result<T>>,
>(&self, fut: F) -> Result<PromiseRaw<'_, T>>
spawn_future_with_callback
INFO
Requires tokio_rt and napi4 feature.
Spawns a future with a callback to process the result.
pub fn spawn_future_with_callback<
T: 'static + Send,
V: ToNapiValue,
F: 'static + Send + Future<Output = Result<T>>,
R: 'static + FnOnce(Env, T) -> Result<V>,
>(&self, fut: F, callback: R) -> Result<PromiseRaw<'_, V>>
Date Creation
create_date
INFO
Requires napi5 feature.
Creates a JavaScript Date object from a timestamp.
pub fn create_date(&self, time: f64) -> Result<JsDate<'_>>
JSON Serialization
to_js_value
INFO
Requires serde-json feature.
Serializes a Rust struct into a JavaScript value using serde.
pub fn to_js_value<'env, T>(&self, node: &T) -> Result<Unknown<'env>>
where
T: Serialize,
from_js_value
INFO
Requires serde-json feature.
Deserializes a JavaScript value into a Rust type using serde.
pub fn from_js_value<'v, T, V>(&self, value: V) -> Result<T>
where
T: DeserializeOwned,
V: JsValue<'v>,
Value Comparison
strict_equals
Performs strict equality comparison between two JavaScript values (equivalent to ===).
pub fn strict_equals<'env, A: JsValue<'env>, B: JsValue<'env>>(
&self,
a: A,
b: B,
) -> Result<bool>