Skip to content

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.

rust
pub fn create_string<S: AsRef<str>>(&self, s: S) -> Result<JsString<'_>>

Example:

rust
let js_string = env.create_string("Hello, World!")?;

create_string_from_std

Creates a JavaScript string from a Rust String.

rust
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.

rust
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.

rust
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.

rust
pub fn create_string_latin1<C: AsRef<[u8]>>(&self, chars: C) -> Result<JsString<'_>>

create_symbol

Creates a JavaScript symbol with an optional description.

rust
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.

rust
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.

rust
pub fn get_last_error_info(&self) -> Result<ExtendedErrorInfo>

throw

Throws any JavaScript value as an exception.

rust
pub fn throw<T: ToNapiValue>(&self, value: T) -> Result<()>

throw_error

Throws a JavaScript Error with the provided message and optional error code.

rust
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.

rust
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.

rust
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.

rust
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.

rust
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.

rust
pub fn fatal_exception(&self, err: Error)

create_error

Creates a JavaScript error object from a Rust Error.

rust
pub fn create_error(&self, e: Error) -> Result<Object<'_>>

Function and Class Creation

create_function

Creates a JavaScript function from a native callback.

rust
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.

lib.rs
rust
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:

index.ts
ts
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.

rust
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:

lib.rs
rust
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)
  })
}

⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️

index.ts
ts
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.

rust
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.

rust
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.

rust
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:

lib.rs
rust
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)
}

⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️

index.d.ts
ts
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:

lib.rs
rust
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.

rust
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.

rust
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.

rust
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.

rust
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.

rust
pub fn run_script<S: AsRef<str>, V: FromNapiValue>(&self, script: S) -> Result<V>

Example:

rust
let result: i32 = env.run_script("2 + 2")?;
assert_eq!(result, 4);

get_napi_version

Gets the N-API version (process.versions.napi).

rust
pub fn get_napi_version(&self) -> Result<u32>

get_node_version

Gets the Node.js version information.

rust
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.

rust
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.

rust
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.

rust
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.

rust
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.

rust
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.

rust
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.

rust
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.

rust
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.

rust
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.

rust
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 ===).

rust
pub fn strict_equals<'env, A: JsValue<'env>, B: JsValue<'env>>(
  &self,
  a: A,
  b: B,
) -> Result<bool>
Last updated on
LongYinan