diff --git a/crates/napi/Cargo.toml b/crates/napi/Cargo.toml index 3528661a..9a5ad420 100644 --- a/crates/napi/Cargo.toml +++ b/crates/napi/Cargo.toml @@ -26,7 +26,7 @@ compat-mode = [] default = ["napi3", "compat-mode"] # for most Node.js users experimental = ["napi-sys/experimental"] chrono_date = ["chrono", "napi5"] -full = ["latin1", "napi8", "async", "serde-json", "experimental", "chrono_date"] +full = ["latin1", "napi9", "async", "serde-json", "experimental", "chrono_date"] latin1 = ["encoding_rs"] error_anyhow = ["anyhow"] napi1 = [] @@ -37,6 +37,7 @@ napi5 = ["napi4", "napi-sys/napi5"] napi6 = ["napi5", "napi-sys/napi6"] napi7 = ["napi6", "napi-sys/napi7"] napi8 = ["napi7", "napi-sys/napi8"] +napi9 = ["napi8", "napi-sys/napi9"] serde-json = ["serde", "serde_json"] tokio_fs = ["tokio/fs"] tokio_full = ["tokio/full"] diff --git a/crates/napi/src/bindgen_runtime/js_values/symbol.rs b/crates/napi/src/bindgen_runtime/js_values/symbol.rs index fef0edb5..39553b59 100644 --- a/crates/napi/src/bindgen_runtime/js_values/symbol.rs +++ b/crates/napi/src/bindgen_runtime/js_values/symbol.rs @@ -6,6 +6,8 @@ use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue}; pub struct Symbol { desc: Option, + #[cfg(feature = "napi9")] + for_desc: Option, } impl TypeName for Symbol { @@ -22,17 +24,43 @@ impl ValidateNapiValue for Symbol {} impl Symbol { pub fn new(desc: String) -> Self { - Self { desc: Some(desc) } + Self { + desc: Some(desc), + #[cfg(feature = "napi9")] + for_desc: None, + } } pub fn identity() -> Self { - Self { desc: None } + Self { + desc: None, + #[cfg(feature = "napi9")] + for_desc: None, + } + } + + #[cfg(feature = "napi9")] + pub fn for_desc(desc: String) -> Self { + Self { + desc: None, + for_desc: Some(desc.to_owned()), + } } } impl ToNapiValue for Symbol { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { let mut symbol_value = ptr::null_mut(); + #[cfg(feature = "napi9")] + if let Some(desc) = val.for_desc { + check_status!( + unsafe { + sys::node_api_symbol_for(env, desc.as_ptr().cast(), desc.len(), &mut symbol_value) + }, + "Failed to call node_api_symbol_for" + )?; + return Ok(symbol_value); + } check_status!(unsafe { sys::napi_create_symbol( env, @@ -63,6 +91,10 @@ impl FromNapiValue for Symbol { _env: sys::napi_env, _napi_val: sys::napi_value, ) -> crate::Result { - Ok(Self { desc: None }) + Ok(Self { + desc: None, + #[cfg(feature = "napi9")] + for_desc: None, + }) } } diff --git a/crates/napi/src/env.rs b/crates/napi/src/env.rs index 37d92157..22c12abb 100644 --- a/crates/napi/src/env.rs +++ b/crates/napi/src/env.rs @@ -1250,6 +1250,18 @@ impl Env { }) } + #[cfg(feature = "napi9")] + pub fn symbol_for(&self, description: &str) -> Result { + let mut result = ptr::null_mut(); + let len = description.len(); + let description = CString::new(description)?; + check_status!(unsafe { + sys::node_api_symbol_for(self.0, description.as_ptr(), len, &mut result) + })?; + + Ok(unsafe { JsSymbol::from_raw_unchecked(self.0, result) }) + } + /// ### Serialize `Rust Struct` into `JavaScript Value` /// /// ``` diff --git a/crates/sys/Cargo.toml b/crates/sys/Cargo.toml index 21c2eb29..4a4fe9a5 100644 --- a/crates/sys/Cargo.toml +++ b/crates/sys/Cargo.toml @@ -21,6 +21,7 @@ napi5 = ["napi4"] napi6 = ["napi5"] napi7 = ["napi6"] napi8 = ["napi7"] +napi9 = ["napi8"] [package.metadata.workspaces] independent = true diff --git a/crates/sys/src/functions.rs b/crates/sys/src/functions.rs index 372f8705..28678466 100644 --- a/crates/sys/src/functions.rs +++ b/crates/sys/src/functions.rs @@ -698,6 +698,24 @@ mod napi8 { ); } +#[cfg(feature = "napi9")] +mod napi9 { + use std::os::raw::c_char; + + use super::super::types::*; + + generate!( + extern "C" { + fn node_api_symbol_for( + env: napi_env, + utf8name: *const c_char, + length: usize, + result: *mut napi_value, + ) -> napi_status; + } + ); +} + #[cfg(feature = "experimental")] mod experimental { use std::os::raw::c_char; @@ -739,6 +757,8 @@ pub use napi6::*; pub use napi7::*; #[cfg(feature = "napi8")] pub use napi8::*; +#[cfg(feature = "napi9")] +pub use napi9::*; #[cfg(windows)] pub(super) unsafe fn load() -> Result { diff --git a/examples/napi-compat-mode/Cargo.toml b/examples/napi-compat-mode/Cargo.toml index 8e483576..9111dadb 100644 --- a/examples/napi-compat-mode/Cargo.toml +++ b/examples/napi-compat-mode/Cargo.toml @@ -9,7 +9,7 @@ version = "0.1.0" crate-type = ["cdylib"] [features] -latest = ["napi/napi8"] +latest = ["napi/napi9"] napi3 = ["napi/napi3"] [dependencies] diff --git a/examples/napi/Cargo.toml b/examples/napi/Cargo.toml index cecb2959..1c10e596 100644 --- a/examples/napi/Cargo.toml +++ b/examples/napi/Cargo.toml @@ -16,7 +16,7 @@ chrono = "0.4" futures = "0.3" napi = { path = "../../crates/napi", default-features = false, features = [ "tokio_fs", - "napi8", + "napi9", "tokio_rt", "serde-json", "async", diff --git a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md index 921209c8..ad5833cf 100644 --- a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md @@ -308,6 +308,8 @@ Generated by [AVA](https://avajs.dev). ␊ export function createSymbol(): symbol␊ ␊ + export function createSymbolFor(desc: string): symbol␊ + ␊ /** You could break the step and for an new continuous value. */␊ export const enum CustomNumEnum {␊ One = 1,␊ diff --git a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap index ec00a215..21386263 100644 Binary files a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap and b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap differ diff --git a/examples/napi/__tests__/values.spec.ts b/examples/napi/__tests__/values.spec.ts index b1765927..6a644e6b 100644 --- a/examples/napi/__tests__/values.spec.ts +++ b/examples/napi/__tests__/values.spec.ts @@ -62,6 +62,7 @@ import { getNull, setSymbolInObj, createSymbol, + createSymbolFor, threadsafeFunctionFatalMode, createExternal, getExternal, @@ -997,3 +998,9 @@ Napi5Test('Date from chrono::NativeDateTime test', (t) => { t.true(fixture instanceof Date) t.is(fixture?.toISOString(), '2016-12-23T15:25:59.325Z') }) + +const Napi9Test = Number(process.versions.napi) >= 9 ? test : test.skip + +Napi9Test('create symbol for', (t) => { + t.is(createSymbolFor('foo'), Symbol.for('foo')) +}) diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index ce84fd02..c3a0e08d 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -298,6 +298,8 @@ export function createObjWithProperty(): { value: ArrayBuffer, get getter(): num export function createSymbol(): symbol +export function createSymbolFor(desc: string): symbol + /** You could break the step and for an new continuous value. */ export const enum CustomNumEnum { One = 1, diff --git a/examples/napi/src/symbol.rs b/examples/napi/src/symbol.rs index cc52be68..3a06425a 100644 --- a/examples/napi/src/symbol.rs +++ b/examples/napi/src/symbol.rs @@ -11,3 +11,8 @@ pub fn set_symbol_in_obj(env: Env, symbol: JsSymbol) -> Result { pub fn create_symbol() -> Symbol { Symbol::new("a symbol".to_owned()) } + +#[napi] +pub fn create_symbol_for(desc: String) -> Symbol { + Symbol::for_desc(desc) +} diff --git a/package.json b/package.json index 3b4bd882..4ec6ecff 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "format:rs": "cargo fmt", "format:toml": "taplo format", "lint": "eslint -c .eslintrc.yml .", - "test": "lerna run test --ignore @napi-rs/cli", + "test": "lerna run test --concurrency=1 --ignore @napi-rs/cli", "test:cli": "yarn workspace @napi-rs/cli test", "test:electron": "electron examples/napi/electron.js", "test:macro": "cargo test -p napi-examples",