Attribute Macro export
#[export]
Expand description
Register an item to be exported by the Neon addon
§Exporting constants and statics
#[neon::export]
static GREETING: &str = "Hello, Neon!";
#[neon::export]
const ANSWER: u8 = 42;
§Renaming an export
By default, items will be exported with their Rust name. Exports may
be renamed by providing the name
attribute.
#[neon::export(name = "myGreeting")]
static GREETING: &str = "Hello, Neon!";
§JSON exports
Complex values may be exported by automatically serializing to JSON and
parsing in JavaScript. Any type that implements serde::Serialize
may be used.
#[neon::export(json)]
static MESSAGES: &[&str] = &["hello", "goodbye"];
§Exporting functions
Functions may take any type that implements TryFromJs
as
an argument and return any type that implements TryIntoJs
.
#[neon::export]
fn add(a: f64, b: f64) -> f64 {
a + b
}
§Naming exported functions
Conventionally, Rust uses snake_case
for function identifiers and JavaScript uses camelCase
.
By default, Neon will attempt to convert function names to camel case. For example:
#[neon::export]
fn add_one(n: f64) -> f64 {
n + 1.0
}
The add_one
function will be exported as addOne
in JavaScript.
import { addOne } from ".";
Similar to globals, exported functions can be overridden with the name
attribute.
#[neon::export(name = "addOneSync")]
fn add_one(n: f64) -> f64 {
n + 1.0
}
Neon uses the following rules when converting snake_case
to camelCase
:
- All leading and trailing underscores (
_
) are preserved - Characters immediately following a non-leading underscore are converted to uppercase
- If the identifier contains an unexpected character, no conversion is performed and
the identifier is used unchanged. Unexpected characters include:
- Uppercase characters
- Duplicate interior (non-leading, non-trailing underscores)
§Exporting a function that uses JSON
The Json
wrapper allows ergonomically handling complex
types that implement serde::Deserialize
and serde::Serialize
.
#[neon::export]
fn sort(Json(mut items): Json<Vec<String>>) -> Json<Vec<String>> {
items.sort();
Json(items)
}
As a convenience, macro uses may add the json
attribute to automatically
wrap arguments and return values with Json
.
#[neon::export(json)]
fn sort(mut items: Vec<String>) -> Vec<String> {
items.sort();
items
}
§Tasks
Neon provides an API for spawning tasks to execute asynchronously on Node’s worker pool. JavaScript may await a promise for completion of the task.
#[neon::export]
fn add<'cx>(cx: &mut FunctionContext<'cx>, a: f64, b: f64) -> JsResult<'cx, JsPromise> {
let promise = cx
.task(move || a + b)
.promise(|mut cx, res| Ok(cx.number(res)));
Ok(promise)
}
As a convenience, macro users may indicate that a function should be executed
asynchronously on the worker pool by adding the task
attribute.
#[neon::export(task)]
fn add(a: f64, b: f64) -> f64 {
a + b
}
§Async Functions
The export
macro can export async fn
, converting to a JavaScript Promise
, if a global
future executor is registered. See neon::set_global_executor
for
more details.
#[neon::export]
async fn add(a: f64, b: f64) -> f64 {
a + b
}
A fn
that returns a Future
can be annotated with #[neon::export(async)]
if it needs to perform some setup on the JavaScript main thread before running asynchronously.
#[neon::export(async)]
fn add(a: f64, b: f64) -> impl Future<Output = f64> {
println!("Hello from the JavaScript main thread!");
async move {
a + b
}
}
If work needs to be performed on the JavaScript main thread after the asynchronous operation,
the With
extractor can be used to execute a closure before returning.
#[neon::export]
async fn add(a: f64, b: f64) -> impl for<'cx> TryIntoJs<'cx> {
let sum = a + b;
With(move |_cx| {
println!("Hello from the JavaScript main thread!");
sum
})
}
§Error Handling
If an exported function returns a Result
, a JavaScript exception will be thrown
with the Err
. Any error type that implements TryIntoJs
may be used.
#[neon::export]
fn throw(msg: String) -> Result<(), String> {
Err(msg)
}
The Error
type is provided for ergonomic error conversions
from most error types using the ?
operator.
use neon::types::extract::Error;
#[neon::export]
fn read_file(path: String) -> Result<String, Error> {
let contents = std::fs::read_to_string(path)?;
Ok(contents)
}
§Interact with the JavaScript runtime
More complex functions may need to interact directly with the JavaScript runtime,
for example with Context
or handles to JavaScript values.
Functions may optionally include a Cx
or
FunctionContext
argument. Note that unlike functions
created with JsFunction::new
, exported function receive a borrowed
context and may require explicit lifetimes.
#[neon::export]
fn add<'cx>(
cx: &mut Cx<'cx>,
a: Handle<JsNumber>,
b: Handle<JsNumber>,
) -> JsResult<'cx, JsNumber> {
let a = a.value(cx);
let b = b.value(cx);
Ok(cx.number(a + b))
}
§Advanced
The following attributes are for advanced configuration and may not be necessary for most users.
§context
The #[neon::export]
uses a heuristic to determine if the first argument
to a function is a context argument.
- In a function executed on the JavaScript main thread, it looks for
&mut Cx
or&mut FunctionContext
to determine if theContext
should be passed. - In a function executed on another thread, it looks for
Channel
.
If the type has been renamed when importing, the context
attribute can be
added to force it to be passed.
use neon::event::Channel as Ch;
use neon::context::FunctionContext as FnCtx;
#[neon::export(context)]
fn add(_cx: &mut FnCtx, a: f64, b: f64) -> f64 {
a + b
}
#[neon::export(context)]
async fn div(_ch: Ch, a: f64, b: f64) -> f64 {
a / b
}
§this
The #[neon::export]
uses a heuristic to determine if an argument to this function is
referring to this
.
- If the first argument is a context, use the 0th argument, otherwise use the 1st.
- If the argument binding is named
this
- Or if it is a tuple struct pattern with an element named
this
use neon::types::extract::Boxed;
#[neon::export]
fn buffer_clone(this: Vec<u8>) -> Vec<u8> {
this
}
#[neon::export]
fn box_to_string(Boxed(this): Boxed<String>) -> String {
this
}
If the function uses a variable name other than this
, the this
attribute may
be added.
#[neon::export(this)]
fn buffer_clone(me: Vec<u8>) -> Vec<u8> {
me
}