refactor!(napi): move JsBigint behind compat-mode feature (#2613)

* refactor!(napi): move JsBigint behind compat-mode feature

* reduce asan flaky
This commit is contained in:
LongYinan 2025-05-08 12:04:02 +08:00 committed by GitHub
parent 813c51e16a
commit c808386a8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 122 additions and 43 deletions

View File

@ -58,6 +58,8 @@ jobs:
RUSTFLAGS: -Z sanitizer=address
ASAN_OPTIONS: detect_leaks=0
NODE_OPTIONS: --max-old-space-size=8192
DISABLE_V8_COMPILE_CACHE: 1
CARGO_PROFILE_DEV_OPT_LEVEL: 1
- name: Clear the cargo caches
run: |

View File

@ -203,6 +203,7 @@ jobs:
run: ${{ matrix.settings.test }}
env:
NODE_OPTIONS: '--max-old-space-size=8192'
DISABLE_V8_COMPILE_CACHE: 1
- name: Electron tests
if: matrix.settings.target == 'aarch64-apple-darwin' || matrix.settings.target == 'x86_64-pc-windows-msvc'

View File

@ -16,7 +16,7 @@ use serde::Serialize;
#[cfg(feature = "napi8")]
use crate::async_cleanup_hook::AsyncCleanupHook;
#[cfg(feature = "napi6")]
#[cfg(all(feature = "napi6", feature = "compat-mode"))]
use crate::bindgen_runtime::u128_with_sign_to_napi_value;
#[cfg(feature = "napi5")]
use crate::bindgen_runtime::FunctionCallContext;
@ -78,6 +78,8 @@ impl Env {
Ok(unsafe { JsBoolean::from_raw_unchecked(self.0, raw_value) })
}
#[cfg(feature = "compat-mode")]
#[deprecated(since = "3.0.0", note = "Use `i32` instead")]
pub fn create_int32(&self, int: i32) -> Result<JsNumber> {
let mut raw_value = ptr::null_mut();
check_status!(unsafe {
@ -86,6 +88,8 @@ impl Env {
unsafe { JsNumber::from_napi_value(self.0, raw_value) }
}
#[cfg(feature = "compat-mode")]
#[deprecated(since = "3.0.0", note = "Use `i64` instead")]
pub fn create_int64(&self, int: i64) -> Result<JsNumber> {
let mut raw_value = ptr::null_mut();
check_status!(unsafe {
@ -94,12 +98,16 @@ impl Env {
unsafe { JsNumber::from_napi_value(self.0, raw_value) }
}
#[cfg(feature = "compat-mode")]
#[deprecated(since = "3.0.0", note = "Use `u32` instead")]
pub fn create_uint32(&self, number: u32) -> Result<JsNumber> {
let mut raw_value = ptr::null_mut();
check_status!(unsafe { sys::napi_create_uint32(self.0, number, &mut raw_value) })?;
unsafe { JsNumber::from_napi_value(self.0, raw_value) }
}
#[cfg(feature = "compat-mode")]
#[deprecated(since = "3.0.0", note = "Use `f64` instead")]
pub fn create_double(&self, double: f64) -> Result<JsNumber> {
let mut raw_value = ptr::null_mut();
check_status!(unsafe {
@ -109,21 +117,24 @@ impl Env {
}
/// [n_api_napi_create_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_int64)
#[cfg(feature = "napi6")]
#[cfg(all(feature = "napi6", feature = "compat-mode"))]
#[deprecated(since = "3.0.0", note = "Use `BigInt` instead")]
pub fn create_bigint_from_i64(&self, value: i64) -> Result<JsBigInt> {
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))
}
#[cfg(feature = "napi6")]
#[cfg(all(feature = "napi6", feature = "compat-mode"))]
#[deprecated(since = "3.0.0", note = "Use `BigInt` instead")]
pub fn create_bigint_from_u64(&self, value: u64) -> Result<JsBigInt> {
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))
}
#[cfg(feature = "napi6")]
#[cfg(all(feature = "napi6", feature = "compat-mode"))]
#[deprecated(since = "3.0.0", note = "Use `BigInt` instead")]
pub fn create_bigint_from_i128(&self, value: i128) -> Result<JsBigInt> {
unsafe {
let raw_value =
@ -132,7 +143,8 @@ impl Env {
}
}
#[cfg(feature = "napi6")]
#[cfg(all(feature = "napi6", feature = "compat-mode"))]
#[deprecated(since = "3.0.0", note = "Use `BigInt` instead")]
pub fn create_bigint_from_u128(&self, value: u128) -> Result<JsBigInt> {
unsafe {
let raw_value = u128_with_sign_to_napi_value(self.0, value, 0)?;
@ -143,7 +155,8 @@ impl Env {
/// [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")]
#[cfg(all(feature = "napi6", feature = "compat-mode"))]
#[deprecated(since = "3.0.0", note = "Use `BigInt` instead")]
pub fn create_bigint_from_words(&self, sign_bit: bool, words: Vec<u64>) -> Result<JsBigInt> {
let mut raw_value = ptr::null_mut();
let len = words.len();

View File

@ -1,13 +1,13 @@
use serde::de::Visitor;
use serde::de::{DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, VariantAccess};
use crate::bindgen_runtime::{BufferSlice, FromNapiValue};
#[cfg(feature = "napi6")]
use crate::JsBigInt;
use crate::{type_of, NapiValue, Value, ValueType};
use crate::{Error, JsObject, JsString, Result, Status, Unknown};
use super::JsArrayBuffer;
use crate::bindgen_runtime::BigInt;
use crate::{
bindgen_runtime::{BufferSlice, FromNapiValue},
type_of, Error, JsArrayBuffer, JsObject, JsString, NapiValue, Result, Status, Unknown, Value,
ValueType,
};
pub struct De<'env>(pub(crate) &'env Value);
impl<'env> De<'env> {
@ -69,16 +69,16 @@ impl<'x> serde::de::Deserializer<'x> for &mut De<'_> {
}
#[cfg(feature = "napi6")]
ValueType::BigInt => {
let mut js_bigint = unsafe { JsBigInt::from_raw(self.0.env, self.0.value)? };
let js_bigint = unsafe { BigInt::from_napi_value(self.0.env, self.0.value)? };
let (signed, words) = js_bigint.get_words()?;
let BigInt { sign_bit, words } = &js_bigint;
let word_sized = words.len() < 2;
match (signed, word_sized) {
(true, true) => visitor.visit_i64(js_bigint.get_i64()?.0),
(true, false) => visitor.visit_i128(js_bigint.get_i128()?.0),
(false, true) => visitor.visit_u64(js_bigint.get_u64()?.0),
(false, false) => visitor.visit_u128(js_bigint.get_u128()?.1),
match (sign_bit, word_sized) {
(true, true) => visitor.visit_i64(js_bigint.get_i64().0),
(true, false) => visitor.visit_i128(js_bigint.get_i128().0),
(false, true) => visitor.visit_u64(js_bigint.get_u64().1),
(false, false) => visitor.visit_u128(js_bigint.get_u128().1),
}
}
ValueType::External | ValueType::Function | ValueType::Symbol => Err(Error::new(

View File

@ -17,7 +17,7 @@ mod de;
mod ser;
mod arraybuffer;
#[cfg(feature = "napi6")]
#[cfg(all(feature = "napi6", feature = "compat-mode"))]
mod bigint;
#[cfg(feature = "compat-mode")]
mod boolean;
@ -43,7 +43,7 @@ mod value;
mod value_ref;
pub use arraybuffer::*;
#[cfg(feature = "napi6")]
#[cfg(all(feature = "napi6", feature = "compat-mode"))]
pub use bigint::JsBigInt;
#[cfg(feature = "compat-mode")]
pub use boolean::JsBoolean;

View File

@ -3,7 +3,10 @@ use std::result::Result as StdResult;
use serde::{ser, Serialize, Serializer};
use super::*;
use crate::{bindgen_runtime::BufferSlice, Env, Error, Result};
use crate::{
bindgen_runtime::{BufferSlice, Null},
Env, Error, Result,
};
pub struct Ser<'env>(pub(crate) &'env Env);
@ -48,39 +51,75 @@ impl Serializer for Ser<'_> {
}
fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
self.0.create_double(v as _).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v)? },
value_type: ValueType::Number,
})
}
fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
self.0.create_double(v).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v)? },
value_type: ValueType::Number,
})
}
fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
self.0.create_int32(v as _).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v as i32)? },
value_type: ValueType::Number,
})
}
fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
self.0.create_int32(v).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v)? },
value_type: ValueType::Number,
})
}
fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
self.0.create_int64(v).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v)? },
value_type: ValueType::Number,
})
}
fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
self.0.create_int32(v as _).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v as i32)? },
value_type: ValueType::Number,
})
}
fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
self.0.create_uint32(v as _).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v as u32)? },
value_type: ValueType::Number,
})
}
fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
self.0.create_uint32(v as _).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v as u32)? },
value_type: ValueType::Number,
})
}
fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
self.0.create_uint32(v).map(|js_number| js_number.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v)? },
value_type: ValueType::Number,
})
}
#[cfg(all(
@ -93,7 +132,14 @@ impl Serializer for Ser<'_> {
not(feature = "napi6")
))]
fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
self.0.create_int64(v as _).map(|js_number| js_number.0)
if v <= u32::MAX.into() {
self.serialize_u32(v as u32)
} else {
Err(Error::new(
Status::InvalidArg,
"u64 is too large to serialize, enable napi6 feature and serialize it as BigInt instead",
))
}
}
#[cfg(feature = "napi6")]
@ -105,10 +151,11 @@ impl Serializer for Ser<'_> {
if v <= u32::MAX.into() {
self.serialize_u32(v as u32)
} else {
self
.0
.create_bigint_from_u64(v)
.map(|js_number| js_number.raw)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v)? },
value_type: ValueType::Number,
})
}
}
@ -122,12 +169,20 @@ impl Serializer for Ser<'_> {
not(feature = "napi6")
))]
fn serialize_u128(self, v: u128) -> Result<Self::Ok> {
self.0.create_string(v.to_string().as_str()).map(|v| v.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v.to_string())? },
value_type: ValueType::Number,
})
}
#[cfg(feature = "napi6")]
fn serialize_u128(self, v: u128) -> Result<Self::Ok> {
self.0.create_bigint_from_u128(v).map(|v| v.raw)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v)? },
value_type: ValueType::Number,
})
}
#[cfg(all(
@ -140,18 +195,26 @@ impl Serializer for Ser<'_> {
not(feature = "napi6")
))]
fn serialize_i128(self, v: i128) -> Result<Self::Ok> {
self.0.create_string(v.to_string().as_str()).map(|v| v.0)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v.to_string())? },
value_type: ValueType::Number,
})
}
#[cfg(feature = "napi6")]
fn serialize_i128(self, v: i128) -> Result<Self::Ok> {
self.0.create_bigint_from_i128(v).map(|v| v.raw)
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, v)? },
value_type: ValueType::Number,
})
}
fn serialize_unit(self) -> Result<Self::Ok> {
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, crate::bindgen_prelude::Null) }?,
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, Null) }?,
value_type: ValueType::Null,
})
}
@ -159,7 +222,7 @@ impl Serializer for Ser<'_> {
fn serialize_none(self) -> Result<Self::Ok> {
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, crate::bindgen_prelude::Null) }?,
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, Null) }?,
value_type: ValueType::Null,
})
}
@ -217,7 +280,7 @@ impl Serializer for Ser<'_> {
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
Ok(Value {
env: self.0.raw(),
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, crate::bindgen_prelude::Null) }?,
value: unsafe { ToNapiValue::to_napi_value(self.0 .0, Null) }?,
value_type: ValueType::Null,
})
}