diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml index a87ff830..4b5aa0ca 100644 --- a/.github/workflows/asan.yml +++ b/.github/workflows/asan.yml @@ -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: | diff --git a/.github/workflows/test-release.yaml b/.github/workflows/test-release.yaml index 9478b237..dd222141 100644 --- a/.github/workflows/test-release.yaml +++ b/.github/workflows/test-release.yaml @@ -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' diff --git a/crates/napi/src/env.rs b/crates/napi/src/env.rs index a0dae1b5..f264c848 100644 --- a/crates/napi/src/env.rs +++ b/crates/napi/src/env.rs @@ -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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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) -> Result { let mut raw_value = ptr::null_mut(); let len = words.len(); diff --git a/crates/napi/src/js_values/de.rs b/crates/napi/src/js_values/de.rs index 019fea7f..c883b841 100644 --- a/crates/napi/src/js_values/de.rs +++ b/crates/napi/src/js_values/de.rs @@ -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( diff --git a/crates/napi/src/js_values/mod.rs b/crates/napi/src/js_values/mod.rs index 78faaeb1..0d2824c5 100644 --- a/crates/napi/src/js_values/mod.rs +++ b/crates/napi/src/js_values/mod.rs @@ -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; diff --git a/crates/napi/src/js_values/ser.rs b/crates/napi/src/js_values/ser.rs index 9cb99e71..9e293881 100644 --- a/crates/napi/src/js_values/ser.rs +++ b/crates/napi/src/js_values/ser.rs @@ -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.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.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.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.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.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.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.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.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.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.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.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.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.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.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 { 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 { 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 { 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, }) }