From b45955458b655baa037cfdd71e6a8ac300441c3e Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Fri, 29 Mar 2024 11:37:20 +0100 Subject: [PATCH] v0.1.6 | Fix `dyn_spawn_blocking()` panicking for cancelled tasks & nits (#209) * Fix `dyn_spawn_blocking` panicking for cancelled tasks * Remove the unused `withOutPtr` js helper * Add `refCBytesIntoBuffer()` js helper * Explain the exact choice of `{MIN,MAX}_SAFE_INTEGER` in js N-API conversions * Version 0.1.6 --- Cargo.lock | 4 +-- Cargo.toml | 4 +-- ffi_tests/Cargo.lock | 4 +-- js_tests/Cargo.lock | 4 +-- src/dyn_traits/futures/executor.rs | 14 +++++++--- src/js/ffi_helpers.rs | 45 +++++++++++++++++------------- src/js/impls.rs | 15 ++++++++-- src/proc_macro/Cargo.toml | 2 +- 8 files changed, 57 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e2b0ae335..b740be9595 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -560,7 +560,7 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "safer-ffi" -version = "0.1.5" +version = "0.1.6" dependencies = [ "async-compat", "cratesio-placeholder-package", @@ -590,7 +590,7 @@ dependencies = [ [[package]] name = "safer_ffi-proc_macros" -version = "0.1.5" +version = "0.1.6" dependencies = [ "macro_rules_attribute", "prettyplease", diff --git a/Cargo.toml b/Cargo.toml index 61aee45b2f..2d0f1fa6fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ path = "src/_lib.rs" [package] name = "safer-ffi" -version = "0.1.5" # Keep in sync +version = "0.1.6" # Keep in sync authors = [ "Daniel Henry-Mantilla ", ] @@ -164,7 +164,7 @@ version = "0.0.3" [dependencies.safer_ffi-proc_macros] path = "src/proc_macro" -version = "=0.1.5" # Keep in sync +version = "=0.1.6" # Keep in sync [workspace] members = [ diff --git a/ffi_tests/Cargo.lock b/ffi_tests/Cargo.lock index c53b3f511a..ef793a5409 100644 --- a/ffi_tests/Cargo.lock +++ b/ffi_tests/Cargo.lock @@ -253,7 +253,7 @@ dependencies = [ [[package]] name = "safer-ffi" -version = "0.1.5" +version = "0.1.6" dependencies = [ "futures", "inventory", @@ -269,7 +269,7 @@ dependencies = [ [[package]] name = "safer_ffi-proc_macros" -version = "0.1.5" +version = "0.1.6" dependencies = [ "macro_rules_attribute", "prettyplease", diff --git a/js_tests/Cargo.lock b/js_tests/Cargo.lock index ec3c121a7f..9902a15c01 100644 --- a/js_tests/Cargo.lock +++ b/js_tests/Cargo.lock @@ -557,7 +557,7 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "safer-ffi" -version = "0.1.5" +version = "0.1.6" dependencies = [ "cratesio-placeholder-package", "inventory", @@ -581,7 +581,7 @@ dependencies = [ [[package]] name = "safer_ffi-proc_macros" -version = "0.1.5" +version = "0.1.6" dependencies = [ "macro_rules_attribute", "prettyplease", diff --git a/src/dyn_traits/futures/executor.rs b/src/dyn_traits/futures/executor.rs index c06893a4bf..f8bfd84654 100644 --- a/src/dyn_traits/futures/executor.rs +++ b/src/dyn_traits/futures/executor.rs @@ -74,7 +74,9 @@ match_! {([] [Send + Sync]) {( $([ $($SendSync:tt)* ])* ) => ( fn spawn_blocking ( self: &'_ Self, action: impl 'static + Send + FnOnce() -> R, - ) -> impl Future> + ) -> impl Future + > { let (tx, rx) = ::futures::channel::oneshot::channel(); let mut action = Some(move || { @@ -84,7 +86,8 @@ match_! {([] [Send + Sync]) {( $([ $($SendSync:tt)* ])* ) => ( action .take() .expect("\ - executor called the `.spawn_blocking()` closure more than once\ + executor called the `.spawn_blocking()` closure \ + more than once\ ") () }; @@ -170,8 +173,11 @@ match_cfg!(feature = "tokio" => { let fut = self.spawn_blocking(|| { action }.call()); let fut = async { fut .await - .unwrap_or_else(|caught_panic| { - ::std::panic::resume_unwind(caught_panic.into_panic()) + .unwrap_or_else(|err| match err.try_into_panic() { + Ok(caught_panic) => { + ::std::panic::resume_unwind(caught_panic); + }, + Err(err) => debug_assert!(err.is_cancelled()), }) }; Box::pin(fut) diff --git a/src/js/ffi_helpers.rs b/src/js/ffi_helpers.rs index ece382125d..78ea8354b4 100644 --- a/src/js/ffi_helpers.rs +++ b/src/js/ffi_helpers.rs @@ -5,6 +5,9 @@ use super::{*, use crate::prelude::*; use ::core::convert::TryFrom; +type JsOf = as ReprNapi>::NapiValue; +type JsOfCSliceRef = JsOf>; + #[js_export(js_name = withCString, __skip_napi_import)] pub fn with_js_string_as_utf8 ( @@ -209,6 +212,29 @@ fn slice_box_uint8_t_to_js_buffer ( } })} +#[js_export(js_name = refCBytesIntoBuffer, __skip_napi_import)] +pub +fn slice_ref_uint8_t_to_js_buffer ( + arg: JsOfCSliceRef, +) -> Result +{Ok({ + let ctx = ::safer_ffi::js::derive::__js_ctx!(); + let fat = crate::slice::slice_ref_Layout::<'_, u8>::from_napi_value(ctx.env, arg)?; + if fat.ptr.is_null() { + ctx .env + .get_null()? + .into_unknown() + } else { + let p: crate::prelude::c_slice::Ref<'_, u8> = unsafe { + crate::layout::from_raw_unchecked(fat) + }; + ctx .env + .create_buffer_copy(p.as_slice())? + .into_unknown() + } +})} + + #[js_export(js_name = withOutBoolean, __skip_napi_import)] pub fn with_out_bool (cb: JsFunction) @@ -260,24 +286,6 @@ fn wrap_ptr (env: &'_ Env, p: *mut (), ty: &'_ str) Ok(obj.into_unknown()) } -#[js_export(js_name = withOutPtr, __skip_napi_import)] -pub -fn with_out_ptr ( - ty: JsString, - cb: JsFunction, -) -> Result -{Ok({ - let ctx = ::safer_ffi::js::derive::__js_ctx!(); - let ref ty: String = ty.into_utf8()?.into_owned()?; - let mut p: *mut () = NULL!(); - let out_p = &mut p; - cb.call(None, &[ - wrap_ptr(ctx.env, <*mut _>::cast(out_p), &format!("{} *", ty))? - ])?; - wrap_ptr(ctx.env, p, ty)? - .into_unknown() -})} - #[js_export(js_name = withOutBoxCBytes, __skip_napi_import)] pub fn with_out_byte_slice (cb: JsFunction) @@ -376,7 +384,6 @@ fn vec_char_ptr_to_js_string_array ( // "refCStringToString": char_p_ref_to_js_string, // "withCBytes": with_js_buffer_as_slice_uint8_t_ref, // "boxCBytesIntoBuffer": slice_box_uint8_t_to_js_buffer, -// "withOutPtr": with_out_ptr, // "withOutBoolean": with_out_bool, // "withOutU64": with_out_u64, // "withOutBoxCBytes": with_out_byte_slice, diff --git a/src/js/impls.rs b/src/js/impls.rs index a91058b246..879f72da82 100644 --- a/src/js/impls.rs +++ b/src/js/impls.rs @@ -129,10 +129,19 @@ match_! {( env: &'_ Env, ) -> Result { - const MIN: i128 = 0 - ((1 << 53) - 1); - const MAX: i128 = 0 + ((1 << 53) - 1); + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER + const MIN_SAFE_INTEGER: i128 = 0 - ((1 << 53) - 1); + /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER + const MAX_SAFE_INTEGER: i128 = 0 + ((1 << 53) - 1); + // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger#description + // we ought not to use the `number` type for integers + // outside of this range lest we expose js code to + // non-"safe integers", _i.e._, integers which break + // mathematical properties such as `x ≠ x + 1`. + // + // See also: https://nodejs.org/api/n-api.html#napi_create_int64 match self as i128 { - | MIN ..= MAX => { + | MIN_SAFE_INTEGER ..= MAX_SAFE_INTEGER => { env .create_int64( self.try_into() .expect("Unreachable") diff --git a/src/proc_macro/Cargo.toml b/src/proc_macro/Cargo.toml index a86d35e2fe..535246df35 100644 --- a/src/proc_macro/Cargo.toml +++ b/src/proc_macro/Cargo.toml @@ -4,7 +4,7 @@ proc-macro = true [package] name = "safer_ffi-proc_macros" -version = "0.1.5" # Keep in sync +version = "0.1.6" # Keep in sync authors = ["Daniel Henry-Mantilla "] edition = "2021"