Skip to content

Commit 2e81ef2

Browse files
committed
feat(neon): Export LazyLock globals
1 parent da5b61d commit 2e81ef2

File tree

5 files changed

+46
-6
lines changed

5 files changed

+46
-6
lines changed

crates/neon-macros/src/export/global/mod.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,9 @@ pub(super) fn export(meta: meta::Meta, name: &syn::Ident, expr: Box<syn::Expr>)
3131
fn #create_name<'cx>(
3232
cx: &mut neon::context::ModuleContext<'cx>,
3333
) -> neon::result::NeonResult<(&'static str, neon::handle::Handle<'cx, neon::types::JsValue>)> {
34-
neon::types::extract::TryIntoJs::try_into_js(#value, cx).map(|v| (
35-
#export_name,
36-
neon::handle::Handle::upcast(&v),
37-
))
34+
use neon::types::extract::TryIntoJs;
35+
36+
(&#value).try_into_js(cx).map(|v| (#export_name, neon::handle::Handle::upcast(&v)))
3837
}
3938
});
4039

crates/neon/src/types_impl/extract/container.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{
22
cell::{Ref, RefCell, RefMut},
33
rc::Rc,
4-
sync::Arc,
4+
sync::{Arc, LazyLock},
55
};
66

77
use crate::{
@@ -10,7 +10,7 @@ use crate::{
1010
result::{JsResult, NeonResult},
1111
types::{
1212
extract::{TryFromJs, TryIntoJs},
13-
JsBox, JsValue,
13+
JsBox, JsValue, Value,
1414
},
1515
};
1616

@@ -124,3 +124,18 @@ where
124124
Ok(JsBox::manually_finalize(cx, self))
125125
}
126126
}
127+
128+
impl<'cx, T, V> TryIntoJs<'cx> for &LazyLock<T>
129+
where
130+
T: 'static,
131+
V: Value,
132+
for<'a> &'a T: TryIntoJs<'cx, Value = V>,
133+
{
134+
type Value = V;
135+
136+
fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
137+
LazyLock::force(&self).try_into_js(cx)
138+
}
139+
}
140+
141+
impl<T> super::private::Sealed for &LazyLock<T> {}

crates/neon/src/types_impl/extract/json.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ where
109109
{
110110
type Value = JsValue;
111111

112+
fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
113+
TryIntoJs::try_into_js(&self, cx)
114+
}
115+
}
116+
117+
impl<'cx, T> TryIntoJs<'cx> for &Json<T>
118+
where
119+
T: serde::Serialize,
120+
{
121+
type Value = JsValue;
122+
112123
fn try_into_js(self, cx: &mut Cx<'cx>) -> JsResult<'cx, Self::Value> {
113124
let s = serde_json::to_string(&self.0).or_else(|err| cx.throw_error(err.to_string()))?;
114125

@@ -118,6 +129,8 @@ where
118129

119130
impl<T> private::Sealed for Json<T> {}
120131

132+
impl<T> private::Sealed for &Json<T> {}
133+
121134
/// Error returned when a value is invalid JSON
122135
pub struct Error(serde_json::Error);
123136

test/napi/lib/export.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ function globals() {
1818
assert.deepStrictEqual(addon.MESSAGES, ["hello", "neon"]);
1919
assert.deepStrictEqual(addon.renamedMessages, ["hello", "neon"]);
2020
});
21+
22+
it("LazyLock", () => {
23+
// Test that LazyLock<String> is exported as a string
24+
assert.strictEqual(typeof addon.LAZY_LOCK_HELLO, "string");
25+
26+
// Test the content matches "Hello, Neon!"
27+
assert.strictEqual(addon.LAZY_LOCK_HELLO, "Hello, Neon!");
28+
});
2129
}
2230

2331
function functions() {

test/napi/src/js/export.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::LazyLock;
2+
13
use neon::{
24
prelude::*,
35
types::extract::{Boxed, Error},
@@ -9,6 +11,9 @@ const NUMBER: u8 = 42;
911
#[neon::export]
1012
static STRING: &str = "Hello, World!";
1113

14+
#[neon::export]
15+
static LAZY_LOCK_HELLO: LazyLock<String> = LazyLock::new(|| String::from("Hello, Neon!"));
16+
1217
#[neon::export(name = "renamedString")]
1318
static RENAMED_STRING: &str = STRING;
1419

0 commit comments

Comments
 (0)