Inject Env
The #[napi]
macro is a very high level abstraction for the Node-API
. Most of the time, you use the Rust native API and crates.
But sometimes you still need to access the low-level Node-API
, for example, to call napi_async_cleanup_hook
(opens in a new tab) or napi_adjust_external_memory
(opens in a new tab).
For this scenario, NAPI-RS allows you to inject Env
into your fn
which is decorated by the #[napi]
.
use napi::{Env, bindgen_prelude::*};
#[napi]
fn call_env(env: Env, length: u32) -> Result<External<Vec<u32>>> {
env.adjust_external_memory(length as i64)?;
Ok(External::new(vec![0; length as usize]))
}
And the Env
will be auto injected by NAPI-RS, it does not affect the arguments
types in the JavaScript side:
export function callEnv(length: number) -> ExternalObject<number[]>
You can also inject Env
in impl
block:
use napi::bindgen_prelude::*;
// A complex struct which can not be exposed into JavaScript directly.
struct QueryEngine {}
#[napi(js_name = "QueryEngine")]
struct JsQueryEngine {
engine: QueryEngine,
}
#[napi]
impl JsQueryEngine {
#[napi(factory)]
pub fn with_initial_count(count: u32) -> Self {
JsQueryEngine { engine: QueryEngine::with_initial_count(count) }
}
/// Class method
#[napi]
pub fn query(&self, env: Env, query: String) -> napi::Result<String> {
self.engine.query(query).map_err(|err| Error::new(Status::GenericFailure, format!("Query failed {}", err)))
}
}
The behavior is just the same with the pure fn
.