feat(napi,sys): implement Symbol.for (#1721)

Co-authored-by: LongYinan <lynweklm@gmail.com>
This commit is contained in:
Tom Sherman 2023-09-14 00:45:14 +02:00 committed by GitHub
parent c853a412b6
commit 3418fd3e8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 89 additions and 7 deletions

View file

@ -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"]

View file

@ -6,6 +6,8 @@ use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
pub struct Symbol {
desc: Option<String>,
#[cfg(feature = "napi9")]
for_desc: Option<String>,
}
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<sys::napi_value> {
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<Self> {
Ok(Self { desc: None })
Ok(Self {
desc: None,
#[cfg(feature = "napi9")]
for_desc: None,
})
}
}

View file

@ -1250,6 +1250,18 @@ impl Env {
})
}
#[cfg(feature = "napi9")]
pub fn symbol_for(&self, description: &str) -> Result<JsSymbol> {
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`
///
/// ```

View file

@ -21,6 +21,7 @@ napi5 = ["napi4"]
napi6 = ["napi5"]
napi7 = ["napi6"]
napi8 = ["napi7"]
napi9 = ["napi8"]
[package.metadata.workspaces]
independent = true

View file

@ -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<libloading::Library, libloading::Error> {

View file

@ -9,7 +9,7 @@ version = "0.1.0"
crate-type = ["cdylib"]
[features]
latest = ["napi/napi8"]
latest = ["napi/napi9"]
napi3 = ["napi/napi3"]
[dependencies]

View file

@ -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",

View file

@ -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,␊

View file

@ -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'))
})

View file

@ -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,

View file

@ -11,3 +11,8 @@ pub fn set_symbol_in_obj(env: Env, symbol: JsSymbol) -> Result<JsObject> {
pub fn create_symbol() -> Symbol {
Symbol::new("a symbol".to_owned())
}
#[napi]
pub fn create_symbol_for(desc: String) -> Symbol {
Symbol::for_desc(desc)
}

View file

@ -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",