neon/sys/
mod.rs

1//! Raw bindings to [Node-API][node-api]
2//!
3//! [Node-API][node-api] is Node.js's API for building native addons. Neon is
4//! predominantly a safe wrapper for Node-API and most users should prefer the
5//! the high level abstractions [outside](crate) of the sys module.
6//!
7//! However, directly using Node-API can be a useful tool for accessing low
8//! level functionality not exposed by Neon or experimenting with extensions
9//! to Neon without needing to fork the project.
10//!
11//! [node-api]: https://nodejs.org/api/n-api.html
12//!
13//! ## Initialization
14//!
15//! Before any Node-API functions may be used, [`setup`] must be called at
16//! least once.
17//!
18//! ```rust,no_run
19//! # #[cfg(feature = "sys")]
20//! # {
21//! # let env = std::ptr::null_mut().cast();
22//! unsafe { neon::sys::setup(env); }
23//! # }
24//! ```
25//! **Note**: It is unnecessary to call [`setup`] if
26//! [`#[neon::main]`](crate::main) is used to initialize the addon.
27//!
28//! ## Safety
29//!
30//! The following are guidelines for ensuring safe usage of Node-API in Neon
31//! but, do not represent a comprehensive set of safety rules. If possible,
32//! users should avoid calling Neon methods or holding references to structures
33//! created by Neon when calling Node-API functions directly.
34//!
35//! ### Env
36//!
37//! Neon ensures safety by carefully restricting access to [`Env`]
38//! by wrapping it in a [`Context`](crate::context::Context). Usages of `Env`
39//! should follow Neon's borrowing rules of `Context`.
40//!
41//! It is unsound to use an `Env` if Rust's borrowing rules would prevent usage
42//! of the in scope `Context`.
43//!
44//! ### Values
45//!
46//! Neon [value types](crate::types) encapsulate references to
47//! [JavaScript values](bindings::Value) with a _known type_. It is unsound to
48//! construct a Neon value with a [`Value`] of the incorrect type.
49//!
50//! ## Example
51//!
52//! ```rust,no_run
53//! # #[cfg(feature = "sys")]
54//! # {
55//! # let env = std::ptr::null_mut().cast();
56//! use neon::{context::Cx, prelude::*, sys::bindings};
57//!
58//! let cx = unsafe {
59//!     neon::sys::setup(env);
60//!
61//!     Cx::from_raw(env)
62//! };
63//!
64//! let raw_string: bindings::Value = cx.string("Hello, World!").to_raw();
65//! let js_string = unsafe { JsString::from_raw(&cx, raw_string) };
66//! # }
67//! ```
68use std::{mem::MaybeUninit, sync::Once};
69
70// Bindings are re-exported here to minimize changes.
71// Follow-up issue: https://github.com/neon-bindings/neon/issues/982
72pub(crate) use bindings::*;
73
74pub(crate) mod array;
75pub(crate) mod arraybuffer;
76pub(crate) mod async_work;
77pub(crate) mod buffer;
78pub(crate) mod call;
79pub(crate) mod convert;
80pub(crate) mod error;
81pub(crate) mod external;
82pub(crate) mod fun;
83pub(crate) mod mem;
84pub(crate) mod no_panic;
85pub(crate) mod object;
86pub(crate) mod primitive;
87pub(crate) mod promise;
88pub(crate) mod raw;
89pub(crate) mod reference;
90pub(crate) mod scope;
91pub(crate) mod string;
92pub(crate) mod tag;
93pub(crate) mod typedarray;
94
95pub mod bindings;
96
97#[cfg(feature = "napi-4")]
98pub(crate) mod tsfn;
99
100#[cfg(feature = "napi-5")]
101pub(crate) mod date;
102
103mod debug_send_wrapper;
104#[cfg(feature = "napi-6")]
105pub(crate) mod lifecycle;
106
107/// Create a JavaScript `String`, panicking if unsuccessful
108///
109/// # Safety
110/// * `env` is a `napi_env` valid for the current thread
111/// * The returned value does not outlive `env`
112unsafe fn string(env: Env, s: impl AsRef<str>) -> raw::Local {
113    let s = s.as_ref();
114    let mut result = MaybeUninit::uninit();
115
116    create_string_utf8(
117        env,
118        s.as_bytes().as_ptr() as *const _,
119        s.len(),
120        result.as_mut_ptr(),
121    )
122    .unwrap();
123
124    result.assume_init()
125}
126
127static SETUP: Once = Once::new();
128
129/// Loads Node-API symbols from the host process.
130///
131/// Must be called at least once before using any functions in bindings or
132/// they will panic.
133///
134/// # Safety
135/// `env` must be a valid `napi_env` for the current thread
136pub unsafe fn setup(env: Env) {
137    SETUP.call_once(|| load(env).expect("Failed to load N-API symbols"));
138}