From 0424a08c0618da2bbc69f41f5c70a083f10666fd Mon Sep 17 00:00:00 2001 From: LongYinan Date: Thu, 11 Nov 2021 00:33:51 +0800 Subject: [PATCH] feat(napi): BigInt codegen support --- README.md | 6 +- crates/backend/src/typegen.rs | 2 + crates/napi/src/bindgen_runtime/js_values.rs | 7 +- .../src/bindgen_runtime/js_values/bigint.rs | 211 ++++++++++++++++++ .../src/bindgen_runtime/js_values/serde.rs | 2 +- crates/napi/src/env.rs | 20 +- crates/napi/src/js_values/bigint.rs | 45 ++-- crates/napi/src/js_values/de.rs | 6 +- crates/napi/src/js_values/mod.rs | 2 +- crates/napi/src/value_type.rs | 4 +- examples/napi-compat-mode/src/napi6/bigint.rs | 16 +- examples/napi/__test__/typegen.spec.ts.md | 3 + examples/napi/__test__/typegen.spec.ts.snap | Bin 923 -> 956 bytes examples/napi/__test__/values.spec.ts | 17 ++ examples/napi/index.d.ts | 3 + examples/napi/src/bigint.rs | 19 ++ examples/napi/src/lib.rs | 1 + examples/napi/tsconfig.json | 2 +- 18 files changed, 313 insertions(+), 53 deletions(-) create mode 100644 crates/napi/src/bindgen_runtime/js_values/bigint.rs create mode 100644 examples/napi/src/bigint.rs diff --git a/README.md b/README.md index 9562378e..2601d706 100644 --- a/README.md +++ b/README.md @@ -241,9 +241,9 @@ yarn test | Result<()> | Error | 1 | v8.0.0 | | T: Fn(...) -> Result | Function | 1 | v8.0.0 | | Async/Future | Promise | 4 | v10.6.0 | async | -| Task | Promise | 1 | v8.5.0 | +| AsyncTask | Promise | 1 | v8.5.0 | | (NOT YET) | global | 1 | v8.0.0 | -| (NOT YET) | Symbol | 1 | v8.0.0 | +| JsSymbol | Symbol | 1 | v8.0.0 | | (NOT YET) | ArrayBuffer/TypedArray | 1 | v8.0.0 | | (NOT YET) | threadsafe function | 4 | v10.6.0 | napi4 | -| (NOT YET) | BigInt | 6 | v10.7.0 | napi6 | +| BigInt | BigInt | 6 | v10.7.0 | napi6 | diff --git a/crates/backend/src/typegen.rs b/crates/backend/src/typegen.rs index 0bbd2e1f..2ea81792 100644 --- a/crates/backend/src/typegen.rs +++ b/crates/backend/src/typegen.rs @@ -40,10 +40,12 @@ static KNOWN_TYPES: Lazy> = Lazy::new(|| { ("u16", "number"), ("u32", "number"), ("u64", "BigInt"), + ("i64n", "BigInt"), ("u128", "BigInt"), ("i128", "BigInt"), ("usize", "BigInt"), ("isize", "BigInt"), + ("JsBigInt", "BigInt"), ("BigInt", "BigInt"), ("bool", "boolean"), ("String", "string"), diff --git a/crates/napi/src/bindgen_runtime/js_values.rs b/crates/napi/src/bindgen_runtime/js_values.rs index f85a0f95..61500a53 100644 --- a/crates/napi/src/bindgen_runtime/js_values.rs +++ b/crates/napi/src/bindgen_runtime/js_values.rs @@ -1,7 +1,10 @@ -use crate::{check_status, sys, Error, JsUnknown, NapiRaw, NapiValue, Result, Status, ValueType}; use std::ptr; +use crate::{check_status, sys, Error, JsUnknown, NapiRaw, NapiValue, Result, Status, ValueType}; + mod array; +#[cfg(feature = "napi6")] +mod bigint; mod boolean; mod buffer; mod either; @@ -15,6 +18,8 @@ mod string; mod task; pub use array::*; +#[cfg(feature = "napi6")] +pub use bigint::*; pub use buffer::*; pub use either::*; pub use nil::*; diff --git a/crates/napi/src/bindgen_runtime/js_values/bigint.rs b/crates/napi/src/bindgen_runtime/js_values/bigint.rs new file mode 100644 index 00000000..c8e42076 --- /dev/null +++ b/crates/napi/src/bindgen_runtime/js_values/bigint.rs @@ -0,0 +1,211 @@ +/// We don't implement `FromNapiValue` for `i64` `u64` `i128` `u128` `isize` `usize` here +/// Because converting directly from `JsBigInt` to these values may result in a loss of precision and thus unintended behavior +/// ```rust +/// use napi::{bindgen_prelude::*, JsBigint}; +/// +/// #[napi] +/// fn bigint_add(mut a: Bigint, mut b: Bigint) -> u128 { +/// a.get_u128().1 + b.get_u128().1 // We have opportunity to check if the `u128` has lost precision +/// } +/// ``` +use std::ptr; + +use crate::{check_status, sys}; + +use super::{FromNapiValue, ToNapiValue, TypeName}; + +/// i64 is converted to `Number` +#[repr(transparent)] +#[allow(non_camel_case_types)] +pub struct i64n(pub i64); + +/// https://nodejs.org/api/n-api.html#napi_create_bigint_words +/// The resulting BigInt is calculated as: (–1)^sign_bit (words[0] × (2^64)^0 + words[1] × (2^64)^1 + …) +pub struct BigInt { + /// true for negative numbers + pub sign_bit: bool, + pub words: Vec, +} + +impl TypeName for BigInt { + fn type_name() -> &'static str { + "BigInt" + } + + fn value_type() -> crate::ValueType { + crate::ValueType::BigInt + } +} + +impl FromNapiValue for BigInt { + unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result { + let mut word_count = 0usize; + check_status!(sys::napi_get_value_bigint_words( + env, + napi_val, + ptr::null_mut(), + &mut word_count, + ptr::null_mut(), + ))?; + let mut words: Vec = Vec::with_capacity(word_count as usize); + let mut sign_bit = 0; + check_status!(sys::napi_get_value_bigint_words( + env, + napi_val, + &mut sign_bit, + &mut word_count, + words.as_mut_ptr(), + ))?; + + words.set_len(word_count as usize); + Ok(BigInt { + sign_bit: sign_bit == 1, + words, + }) + } +} + +impl BigInt { + /// (signed, value, lossless) + /// get the first word of the BigInt as `u64` + /// return true in the last element of tuple if the value is lossless + /// or the value is truncated + pub fn get_u64(&self) -> (bool, u64, bool) { + ( + self.sign_bit, + self.words[0], + self.sign_bit && self.words.len() == 1, + ) + } + + /// (value, lossless) + /// get the first word of the BigInt as `i64` + /// return true if the value is lossless + /// or the value is truncated + pub fn get_i64(&self) -> (i64, bool) { + let val = self.words[0] as i64; + (val, val as u64 == self.words[0] && self.words.len() == 1) + } + + /// (value, lossless) + /// get the first two words of the BigInt as `i128` + /// return true if the value is lossless + /// or the value is truncated + pub fn get_i128(&self) -> (i128, bool) { + let len = self.words.len(); + if len == 1 { + (self.words[0] as i128, false) + } else { + let i128_words: [i64; 2] = [self.words[0] as _, self.words[1] as _]; + let mut val = unsafe { ptr::read(i128_words.as_ptr() as *const i128) }; + if self.sign_bit { + val = -val; + } + (val, len > 2) + } + } + + /// (signed, value, lossless) + /// get the first two words of the BigInt as `u128` + /// return true if the value is lossless + /// or the value is truncated + pub fn get_u128(&self) -> (bool, u128, bool) { + let len = self.words.len(); + if len == 1 { + (self.sign_bit, self.words[0] as u128, false) + } else { + let u128_words: [u64; 2] = [self.words[0], self.words[1]]; + let val = unsafe { ptr::read(u128_words.as_ptr() as *const u128) }; + (self.sign_bit, val, len > 2) + } + } +} + +impl ToNapiValue for BigInt { + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { + let mut raw_value = ptr::null_mut(); + let len = val.words.len(); + check_status!(sys::napi_create_bigint_words( + env, + match val.sign_bit { + true => 1, + false => 0, + }, + len, + val.words.as_ptr(), + &mut raw_value, + ))?; + Ok(raw_value) + } +} + +impl ToNapiValue for i128 { + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { + let mut raw_value = ptr::null_mut(); + let sign_bit = if val > 0 { 0 } else { 1 }; + let words = &val as *const i128 as *const u64; + check_status!(sys::napi_create_bigint_words( + env, + sign_bit, + 2, + words, + &mut raw_value + ))?; + Ok(raw_value) + } +} + +impl ToNapiValue for u128 { + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { + let mut raw_value = ptr::null_mut(); + let words = &val as *const u128 as *const u64; + check_status!(sys::napi_create_bigint_words( + env, + 0, + 2, + words, + &mut raw_value + ))?; + Ok(raw_value) + } +} + +impl ToNapiValue for i64n { + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { + let mut raw_value = ptr::null_mut(); + check_status!(sys::napi_create_bigint_int64(env, val.0, &mut raw_value))?; + Ok(raw_value) + } +} + +impl ToNapiValue for u64 { + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { + let mut raw_value = ptr::null_mut(); + check_status!(sys::napi_create_bigint_uint64(env, val, &mut raw_value))?; + Ok(raw_value) + } +} + +impl ToNapiValue for usize { + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { + let mut raw_value = ptr::null_mut(); + check_status!(sys::napi_create_bigint_uint64( + env, + val as u64, + &mut raw_value + ))?; + Ok(raw_value) + } +} + +impl ToNapiValue for isize { + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result { + let mut raw_value = ptr::null_mut(); + check_status!(sys::napi_create_bigint_int64( + env, + val as i64, + &mut raw_value + ))?; + Ok(raw_value) + } +} diff --git a/crates/napi/src/bindgen_runtime/js_values/serde.rs b/crates/napi/src/bindgen_runtime/js_values/serde.rs index 988c239f..ff1add21 100644 --- a/crates/napi/src/bindgen_runtime/js_values/serde.rs +++ b/crates/napi/src/bindgen_runtime/js_values/serde.rs @@ -56,7 +56,7 @@ impl FromNapiValue for Value { } } #[cfg(feature = "napi6")] - ValueType::Bigint => todo!(), + ValueType::BigInt => todo!(), _ => Value::Null, }; diff --git a/crates/napi/src/env.rs b/crates/napi/src/env.rs index 2e6189e8..999dbe42 100644 --- a/crates/napi/src/env.rs +++ b/crates/napi/src/env.rs @@ -100,43 +100,43 @@ impl Env { /// [n_api_napi_create_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_int64) #[cfg(feature = "napi6")] - pub fn create_bigint_from_i64(&self, value: i64) -> Result { + pub fn create_bigint_from_i64(&self, value: i64) -> Result { let mut raw_value = ptr::null_mut(); check_status!(unsafe { sys::napi_create_bigint_int64(self.0, value, &mut raw_value) })?; - Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1)) + Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 1)) } #[cfg(feature = "napi6")] - pub fn create_bigint_from_u64(&self, value: u64) -> Result { + pub fn create_bigint_from_u64(&self, value: u64) -> Result { let mut raw_value = ptr::null_mut(); check_status!(unsafe { sys::napi_create_bigint_uint64(self.0, value, &mut raw_value) })?; - Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1)) + Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 1)) } #[cfg(feature = "napi6")] - pub fn create_bigint_from_i128(&self, value: i128) -> Result { + pub fn create_bigint_from_i128(&self, value: i128) -> Result { let mut raw_value = ptr::null_mut(); let sign_bit = if value > 0 { 0 } else { 1 }; let words = &value as *const i128 as *const u64; check_status!(unsafe { sys::napi_create_bigint_words(self.0, sign_bit, 2, words, &mut raw_value) })?; - Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1)) + Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 1)) } #[cfg(feature = "napi6")] - pub fn create_bigint_from_u128(&self, value: u128) -> Result { + pub fn create_bigint_from_u128(&self, value: u128) -> Result { let mut raw_value = ptr::null_mut(); let words = &value as *const u128 as *const u64; check_status!(unsafe { sys::napi_create_bigint_words(self.0, 0, 2, words, &mut raw_value) })?; - Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1)) + Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, 1)) } /// [n_api_napi_create_bigint_words](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_words) /// /// The resulting BigInt will be negative when sign_bit is true. #[cfg(feature = "napi6")] - pub fn create_bigint_from_words(&self, sign_bit: bool, words: Vec) -> Result { + pub fn create_bigint_from_words(&self, sign_bit: bool, words: Vec) -> Result { let mut raw_value = ptr::null_mut(); let len = words.len(); check_status!(unsafe { @@ -151,7 +151,7 @@ impl Env { &mut raw_value, ) })?; - Ok(JsBigint::from_raw_unchecked(self.0, raw_value, len)) + Ok(JsBigInt::from_raw_unchecked(self.0, raw_value, len)) } pub fn create_string(&self, s: &str) -> Result { diff --git a/crates/napi/src/js_values/bigint.rs b/crates/napi/src/js_values/bigint.rs index dd295b4b..8eeef285 100644 --- a/crates/napi/src/js_values/bigint.rs +++ b/crates/napi/src/js_values/bigint.rs @@ -5,22 +5,22 @@ use super::*; use crate::{bindgen_runtime::TypeName, check_status, sys, Result}; #[derive(Clone, Copy)] -pub struct JsBigint { +pub struct JsBigInt { pub(crate) raw: Value, pub word_count: usize, } -impl TypeName for JsBigint { +impl TypeName for JsBigInt { fn type_name() -> &'static str { "BigInt" } fn value_type() -> ValueType { - ValueType::Bigint + ValueType::BigInt } } -impl JsBigint { +impl JsBigInt { pub(crate) fn from_raw_unchecked( env: sys::napi_env, value: sys::napi_value, @@ -76,7 +76,6 @@ impl JsBigint { })) } - #[cfg(feature = "napi5")] pub fn is_date(&self) -> Result { let mut is_date = true; check_status!(unsafe { sys::napi_is_date(self.raw.env, self.raw.value, &mut is_date) })?; @@ -122,19 +121,19 @@ impl JsBigint { } } -impl NapiRaw for JsBigint { +impl NapiRaw for JsBigInt { unsafe fn raw(&self) -> sys::napi_value { self.raw.value } } -impl<'env> NapiRaw for &'env JsBigint { +impl<'env> NapiRaw for &'env JsBigInt { unsafe fn raw(&self) -> sys::napi_value { self.raw.value } } -impl NapiValue for JsBigint { +impl NapiValue for JsBigInt { unsafe fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result { let mut word_count = 0usize; check_status!(sys::napi_get_value_bigint_words( @@ -144,11 +143,11 @@ impl NapiValue for JsBigint { &mut word_count, ptr::null_mut(), ))?; - Ok(JsBigint { + Ok(JsBigInt { raw: Value { env, value, - value_type: ValueType::Bigint, + value_type: ValueType::BigInt, }, word_count, }) @@ -167,11 +166,11 @@ impl NapiValue for JsBigint { Status::from(status) == Status::Ok, "napi_get_value_bigint_words failed" ); - JsBigint { + JsBigInt { raw: Value { env, value, - value_type: ValueType::Bigint, + value_type: ValueType::BigInt, }, word_count, } @@ -179,24 +178,24 @@ impl NapiValue for JsBigint { } /// The BigInt will be converted losslessly when the value is over what an int64 could hold. -impl TryFrom for i64 { +impl TryFrom for i64 { type Error = Error; - fn try_from(value: JsBigint) -> Result { + fn try_from(value: JsBigInt) -> Result { value.get_i64().map(|(v, _)| v) } } /// The BigInt will be converted losslessly when the value is over what an uint64 could hold. -impl TryFrom for u64 { +impl TryFrom for u64 { type Error = Error; - fn try_from(value: JsBigint) -> Result { + fn try_from(value: JsBigInt) -> Result { value.get_u64().map(|(v, _)| v) } } -impl JsBigint { +impl JsBigInt { /// https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_words pub fn get_words(&mut self) -> Result<(bool, Vec)> { let mut words: Vec = Vec::with_capacity(self.word_count as usize); @@ -221,21 +220,21 @@ impl JsBigint { pub fn get_u64(&self) -> Result<(u64, bool)> { let mut val: u64 = 0; - let mut loss = false; + let mut lossless = false; check_status!(unsafe { - sys::napi_get_value_bigint_uint64(self.raw.env, self.raw.value, &mut val, &mut loss) + sys::napi_get_value_bigint_uint64(self.raw.env, self.raw.value, &mut val, &mut lossless) })?; - Ok((val, loss)) + Ok((val, lossless)) } pub fn get_i64(&self) -> Result<(i64, bool)> { let mut val: i64 = 0; - let mut loss: bool = false; + let mut lossless: bool = false; check_status!(unsafe { - sys::napi_get_value_bigint_int64(self.raw.env, self.raw.value, &mut val, &mut loss) + sys::napi_get_value_bigint_int64(self.raw.env, self.raw.value, &mut val, &mut lossless) })?; - Ok((val, loss)) + Ok((val, lossless)) } pub fn get_i128(&mut self) -> Result<(i128, bool)> { diff --git a/crates/napi/src/js_values/de.rs b/crates/napi/src/js_values/de.rs index 96c080bd..425f6b52 100644 --- a/crates/napi/src/js_values/de.rs +++ b/crates/napi/src/js_values/de.rs @@ -4,7 +4,7 @@ use serde::de::Visitor; use serde::de::{DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, VariantAccess}; #[cfg(feature = "napi6")] -use crate::JsBigint; +use crate::JsBigInt; use crate::{type_of, NapiValue, Value, ValueType}; use crate::{ Error, JsBoolean, JsBufferValue, JsNumber, JsObject, JsString, JsUnknown, Result, Status, @@ -54,8 +54,8 @@ impl<'x, 'de, 'env> serde::de::Deserializer<'x> for &'de mut De<'env> { } } #[cfg(feature = "napi6")] - ValueType::Bigint => { - let mut js_bigint = unsafe { JsBigint::from_raw(self.0.env, self.0.value)? }; + ValueType::BigInt => { + let mut js_bigint = unsafe { JsBigInt::from_raw(self.0.env, self.0.value)? }; let (signed, v, _loss) = js_bigint.get_u128()?; if signed { visitor.visit_i128(-(v as i128)) diff --git a/crates/napi/src/js_values/mod.rs b/crates/napi/src/js_values/mod.rs index 4ab96f17..b0e386cf 100644 --- a/crates/napi/src/js_values/mod.rs +++ b/crates/napi/src/js_values/mod.rs @@ -33,7 +33,7 @@ mod value_ref; pub use arraybuffer::*; #[cfg(feature = "napi6")] -pub use bigint::JsBigint; +pub use bigint::JsBigInt; pub use boolean::JsBoolean; pub use buffer::*; #[cfg(feature = "napi5")] diff --git a/crates/napi/src/value_type.rs b/crates/napi/src/value_type.rs index 5320522a..61129665 100644 --- a/crates/napi/src/value_type.rs +++ b/crates/napi/src/value_type.rs @@ -15,7 +15,7 @@ pub enum ValueType { Function = 7, External = 8, #[cfg(feature = "napi6")] - Bigint = 9, + BigInt = 9, Unknown = 1024, } @@ -30,7 +30,7 @@ impl From for ValueType { fn from(value: i32) -> ValueType { match value { #[cfg(feature = "napi6")] - sys::ValueType::napi_bigint => ValueType::Bigint, + sys::ValueType::napi_bigint => ValueType::BigInt, sys::ValueType::napi_boolean => ValueType::Boolean, sys::ValueType::napi_external => ValueType::External, sys::ValueType::napi_function => ValueType::Function, diff --git a/examples/napi-compat-mode/src/napi6/bigint.rs b/examples/napi-compat-mode/src/napi6/bigint.rs index 2bd6eada..15b57ae0 100644 --- a/examples/napi-compat-mode/src/napi6/bigint.rs +++ b/examples/napi-compat-mode/src/napi6/bigint.rs @@ -1,28 +1,28 @@ -use napi::{CallContext, JsBigint, JsNumber, JsObject, Result}; +use napi::{CallContext, JsBigInt, JsNumber, JsObject, Result}; use std::convert::TryFrom; #[js_function] -pub fn test_create_bigint_from_i64(ctx: CallContext) -> Result { +pub fn test_create_bigint_from_i64(ctx: CallContext) -> Result { ctx.env.create_bigint_from_i64(i64::max_value()) } #[js_function] -pub fn test_create_bigint_from_u64(ctx: CallContext) -> Result { +pub fn test_create_bigint_from_u64(ctx: CallContext) -> Result { ctx.env.create_bigint_from_u64(u64::max_value()) } #[js_function] -pub fn test_create_bigint_from_i128(ctx: CallContext) -> Result { +pub fn test_create_bigint_from_i128(ctx: CallContext) -> Result { ctx.env.create_bigint_from_i128(i128::max_value()) } #[js_function] -pub fn test_create_bigint_from_u128(ctx: CallContext) -> Result { +pub fn test_create_bigint_from_u128(ctx: CallContext) -> Result { ctx.env.create_bigint_from_u128(u128::max_value()) } #[js_function] -pub fn test_create_bigint_from_words(ctx: CallContext) -> Result { +pub fn test_create_bigint_from_words(ctx: CallContext) -> Result { ctx .env .create_bigint_from_words(true, vec![u64::max_value(), u64::max_value()]) @@ -30,14 +30,14 @@ pub fn test_create_bigint_from_words(ctx: CallContext) -> Result { #[js_function(1)] pub fn test_get_bigint_i64(ctx: CallContext) -> Result { - let js_bigint = ctx.get::(0)?; + let js_bigint = ctx.get::(0)?; let val = i64::try_from(js_bigint)?; ctx.env.create_int32(val as i32) } #[js_function(1)] pub fn test_get_bigint_u64(ctx: CallContext) -> Result { - let js_bigint = ctx.get::(0)?; + let js_bigint = ctx.get::(0)?; let val = u64::try_from(js_bigint)?; ctx.env.create_int32(val as i32) } diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 4f2bb9cf..66ac07d0 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -13,6 +13,9 @@ Generated by [AVA](https://avajs.dev). export function sumNums(nums: Array): number␊ export function readFileAsync(path: string): Promise␊ export function asyncMultiTwo(arg: number): Promise␊ + export function bigintAdd(a: BigInt, b: BigInt): BigInt␊ + export function createBigInt(): BigInt␊ + export function createBigIntI64(): BigInt␊ export function getCwd(callback: (arg0: string) => void): void␊ export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void␊ export function eitherStringOrNumber(input: string | number): number␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index d92c080ac4ad25d7b8c5e7a0eac488bbcd2d9f33..17956eb968ca791f2c5388439da84a91c119bda9 100644 GIT binary patch literal 956 zcmV;t14H~lRzV**3r^d@1xT4qs z^i~w;z309{k2z;ZSzg()YWpA$#c#fkGn^Sg5Cl8HlV6|y^Y?#0|MA(AeJ z0{8oNHwc~tUwM1y%ix(2+*KA8IFFaN4yzp6J={Uh*hbS4bQaN(@C{H(wddL%m z>-Zzw?*iPmWga?&jy4LBMZB$Ok(TgU$Q173TxIYI_Ch%0mW=%n&dX#>)&V>$;m=BA zm1~>}x4MUGi4~qo+QG>fX>{)nL%39>ChI7K8*xX*aR?V88##p+Aq<4~{f=BvI+8tD z6C=sIQ&)!v45MZ7?%T5?t){-5SXY%4d~!W;7Q5wn^q4VUVk_%*A6H#ifqWNks;8ld zmE=hxnA{A`g|T#BuW@FWia$m`4@~UF$yfC-dAg`8pGIZ9pzZ)| zhuRQH<4uYaq*j!PK$?$lF`@Z8*QU;tvy(bK4tjgOExLWhZX`5L=T6^Pt{Xs&?E!^B zb9k{{@?A7*J6B3tE~H_GN;Fv{A_Pk_2W?}h&wFScL&7c18CI0`rs2@7Nci`5xPQ#d zw(uXh6>@(Y{FG*aDs4Zew`UZbR(VddtD{UeeQg}uHdG-PkxAD<9)05%TkungtB<7r z(0HrHBsn(*`cf1;_l4@pL&T`GQ>lZ)C=|IM}1fh>@??NJUIQH8yej{zLi7b zjE!*?&4Dqkd(pC22PGjZzLjlvg?MLct!Cm@5_HZjXDK}z;wV1ZO&X(Q@Y9rye| eG?(0w&(=+uhS;E$*{DT95}yG8=tze+3IG6F@WxsI literal 923 zcmV;M17!R`RzV+ty1LP z>1CNa`DUycH~mVc=G%5#3hQW`F~RdZk5YEzfaCHyhqA7FTBJ^;r5Lv|Ah!$xHFQm%g3XXLjp2Btv zN8FLI6T@*ShGgx+^#cB=v`+haJ@Kn6I8!*qQzdyg83TiUZ!d;ZT^h0;#&9k#$#@*Y ziR=%&!f!EjW$^u-Tu^zEZCDW_$-L3e_jVa3i{kCC=LSZPLpiawDk=ErY~(F=!Sm!M zW1+;B*3I_GGR7-V3~92qo_aFXiVGo`S`W^pb@W~@aAKKG-z7jF6mIRn5!71_$~<~pMnaZ=sv-db!rV@tIcK3@j&xJE@G!L#6y!b2z6#x zyGO006xE%A)`P diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index 479e8810..c00f1c8c 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -35,6 +35,9 @@ import { withoutAbortController, withAbortController, asyncMultiTwo, + bigintAdd, + createBigInt, + createBigIntI64, } from '../' test('number', (t) => { @@ -217,3 +220,17 @@ MaybeTest('abort resolved task', async (t) => { await withAbortController(1, 2, ctrl.signal).then(() => ctrl.abort()) t.pass('should not throw') }) + +const BigIntTest = typeof BigInt !== 'undefined' ? test : test.skip + +BigIntTest('BigInt add', (t) => { + t.is(bigintAdd(BigInt(1), BigInt(2)), BigInt(3)) +}) + +BigIntTest('create BigInt', (t) => { + t.is(createBigInt(), BigInt('-3689348814741910323300')) +}) + +BigIntTest('create BigInt i64', (t) => { + t.is(createBigIntI64(), BigInt(100)) +}) diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index ab2e701d..66f9791c 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -3,6 +3,9 @@ export function getNums(): Array export function sumNums(nums: Array): number export function readFileAsync(path: string): Promise export function asyncMultiTwo(arg: number): Promise +export function bigintAdd(a: BigInt, b: BigInt): BigInt +export function createBigInt(): BigInt +export function createBigIntI64(): BigInt export function getCwd(callback: (arg0: string) => void): void export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void export function eitherStringOrNumber(input: string | number): number diff --git a/examples/napi/src/bigint.rs b/examples/napi/src/bigint.rs new file mode 100644 index 00000000..80decf96 --- /dev/null +++ b/examples/napi/src/bigint.rs @@ -0,0 +1,19 @@ +use napi::bindgen_prelude::*; + +#[napi] +fn bigint_add(a: BigInt, b: BigInt) -> u128 { + a.get_u128().1 + b.get_u128().1 +} + +#[napi] +fn create_big_int() -> BigInt { + BigInt { + words: vec![100u64, 200u64], + sign_bit: true, + } +} + +#[napi] +fn create_big_int_i64() -> i64n { + i64n(100) +} diff --git a/examples/napi/src/lib.rs b/examples/napi/src/lib.rs index 5da94157..bece1e32 100644 --- a/examples/napi/src/lib.rs +++ b/examples/napi/src/lib.rs @@ -5,6 +5,7 @@ extern crate serde_derive; mod array; mod r#async; +mod bigint; mod callback; mod class; mod class_factory; diff --git a/examples/napi/tsconfig.json b/examples/napi/tsconfig.json index dead17fc..4a99370d 100644 --- a/examples/napi/tsconfig.json +++ b/examples/napi/tsconfig.json @@ -4,7 +4,7 @@ "compilerOptions": { "outDir": "./dist", "rootDir": "__test__", - "target": "ES2015" + "target": "ES2018" }, "exclude": ["dist", "index.d.ts"] }