fix(napi): big numbers losing precision on serde_json::Value ()

* fix(napi): big numbers losing precision on serde_json::Value

* fix(napi): add feature flags for bigint on number conversion

* chore(napi): change MAX_SAFE_INT to constant and convert big numbers to string when bigint is not available

* chore(napi): change how the check for safe integer range is made
This commit is contained in:
Gabriel Francisco 2023-03-23 02:34:34 -03:00 committed by GitHub
parent 2e865cad29
commit 3983be23f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 2 deletions
crates/napi/src/bindgen_runtime/js_values

View file

@ -4,6 +4,8 @@ use crate::{
bindgen_runtime::Null, check_status, sys, type_of, Error, JsObject, Result, Status, ValueType,
};
#[cfg(feature = "napi6")]
use super::BigInt;
use super::{FromNapiValue, Object, ToNapiValue};
impl ToNapiValue for Value {
@ -111,14 +113,30 @@ impl FromNapiValue for Map<String, Value> {
impl ToNapiValue for Number {
unsafe fn to_napi_value(env: sys::napi_env, n: Self) -> Result<sys::napi_value> {
#[cfg(feature = "napi6")]
const MAX_SAFE_INT: i64 = 9007199254740991i64; // 2 ^ 53 - 1
if n.is_i64() {
unsafe { i64::to_napi_value(env, n.as_i64().unwrap()) }
let n = n.as_i64().unwrap();
#[cfg(feature = "napi6")]
{
if !(-MAX_SAFE_INT..=MAX_SAFE_INT).contains(&n) {
return unsafe { BigInt::to_napi_value(env, BigInt::from(n)) };
}
}
unsafe { i64::to_napi_value(env, n) }
} else if n.is_f64() {
unsafe { f64::to_napi_value(env, n.as_f64().unwrap()) }
} else {
let n = n.as_u64().unwrap();
if n > u32::MAX as u64 {
todo!("impl BigInt")
#[cfg(feature = "napi6")]
{
return unsafe { BigInt::to_napi_value(env, BigInt::from(n)) };
}
#[cfg(not(feature = "napi6"))]
return unsafe { String::to_napi_value(env, n.to_string()) };
} else {
unsafe { u32::to_napi_value(env, n as u32) }
}