From a7eeb0c31c2847cb4cffad4eebc63ad7f1842d8a Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 24 Jul 2023 00:36:24 +0800 Subject: [PATCH] fix(napi): promise resolve error (#1664) --- .github/workflows/test-release.yaml | 16 +- crates/napi/src/async_work.rs | 7 +- .../src/bindgen_runtime/js_values/promise.rs | 5 +- .../src/bindgen_runtime/js_values/string.rs | 12 +- .../src/bindgen_runtime/js_values/task.rs | 2 +- .../bindgen_runtime/js_values/value_ref.rs | 2 +- crates/napi/src/env.rs | 10 +- crates/napi/src/error.rs | 67 ++---- crates/napi/src/js_values/deferred.rs | 215 +++++++++--------- crates/napi/src/js_values/mod.rs | 40 ++-- crates/napi/src/threadsafe_function.rs | 48 ++-- examples/napi/src/either.rs | 2 + 12 files changed, 212 insertions(+), 214 deletions(-) diff --git a/.github/workflows/test-release.yaml b/.github/workflows/test-release.yaml index 309f5739..152b3a37 100644 --- a/.github/workflows/test-release.yaml +++ b/.github/workflows/test-release.yaml @@ -124,7 +124,7 @@ jobs: - settings: target: i686-pc-windows-msvc node: 18 - name: stable - ${{ matrix.settings.host }} - node@${{ matrix.node }} + name: ${{ matrix.settings.host }} - node@${{ matrix.node }} - toolchain@ ${{ matrix.settings.toolchain }} runs-on: ${{ matrix.settings.host }} steps: @@ -292,6 +292,8 @@ jobs: options: -v ${{ github.workspace }}/.cargo-cache/registry:/usr/local/cargo/registry -v ${{ github.workspace }}/.cargo-cache/git:/usr/local/cargo/git -v ${{ github.workspace }}:/napi-rs -w /napi-rs run: | yarn build:test -- --target ${{ matrix.settings.target }} + chmod 777 -R .cargo-cache + chmod 777 -R target - uses: actions/upload-artifact@v3 with: @@ -365,8 +367,16 @@ jobs: uses: addnab/docker-run-action@v3 with: image: ${{ steps.image-name.outputs.docker-image }} - options: ${{ matrix.settings.args }} -v ${{ github.workspace }}:/build -w /build - run: yarn test + options: ${{ matrix.settings.args }} -v ${{ github.workspace }}/cores:/cores -v ${{ github.workspace }}:/build -w /build + run: >- + ulimit -c && + ulimit -c unlimited && + ulimit -c && + yarn test + - name: List files + run: | + ls -la . + ls -la ./cores build-and-test-linux-armv7: name: stable - armv7-unknown-linux-gnu - node@18 diff --git a/crates/napi/src/async_work.rs b/crates/napi/src/async_work.rs index 0acd3a84..acd29b69 100644 --- a/crates/napi/src/async_work.rs +++ b/crates/napi/src/async_work.rs @@ -72,11 +72,8 @@ pub fn run( env, raw_resource, async_work_name, - Some(execute:: as unsafe extern "C" fn(env: sys::napi_env, data: *mut c_void)), - Some( - complete:: - as unsafe extern "C" fn(env: sys::napi_env, status: sys::napi_status, data: *mut c_void), - ), + Some(execute::), + Some(complete::), (result as *mut AsyncWork).cast(), &mut result.napi_async_work, ) diff --git a/crates/napi/src/bindgen_runtime/js_values/promise.rs b/crates/napi/src/bindgen_runtime/js_values/promise.rs index 09fe1fd8..0647000e 100644 --- a/crates/napi/src/bindgen_runtime/js_values/promise.rs +++ b/crates/napi/src/bindgen_runtime/js_values/promise.rs @@ -81,7 +81,10 @@ impl ValidateNapiValue for Promise { unsafe { crate::sys::napi_create_error(env, code, message, &mut err) }, "Failed to create rejected error" )?; - check_status!(unsafe { crate::sys::napi_reject_deferred(env, deferred, err) })?; + check_status!( + unsafe { crate::sys::napi_reject_deferred(env, deferred, err) }, + "Failed to reject promise in validate" + )?; return Ok(promise); } Ok(ptr::null_mut()) diff --git a/crates/napi/src/bindgen_runtime/js_values/string.rs b/crates/napi/src/bindgen_runtime/js_values/string.rs index 75d931b9..82a87b85 100644 --- a/crates/napi/src/bindgen_runtime/js_values/string.rs +++ b/crates/napi/src/bindgen_runtime/js_values/string.rs @@ -18,7 +18,7 @@ impl TypeName for String { impl ValidateNapiValue for String {} -impl ToNapiValue for String { +impl ToNapiValue for &String { unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { let mut ptr = ptr::null_mut(); @@ -31,6 +31,16 @@ impl ToNapiValue for String { } } +impl ToNapiValue for String { + #[inline] + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { + #[allow(clippy::needless_borrow)] + unsafe { + ToNapiValue::to_napi_value(env, &val) + } + } +} + impl FromNapiValue for String { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result { let mut len = 0; diff --git a/crates/napi/src/bindgen_runtime/js_values/task.rs b/crates/napi/src/bindgen_runtime/js_values/task.rs index bd746fcc..11b551a8 100644 --- a/crates/napi/src/bindgen_runtime/js_values/task.rs +++ b/crates/napi/src/bindgen_runtime/js_values/task.rs @@ -159,5 +159,5 @@ unsafe extern "C" fn async_task_abort_controller_finalize( finalize_data: *mut c_void, _finalize_hint: *mut c_void, ) { - unsafe { Box::from_raw(finalize_data as *mut AbortSignal) }; + drop(unsafe { Box::from_raw(finalize_data as *mut AbortSignal) }); } diff --git a/crates/napi/src/bindgen_runtime/js_values/value_ref.rs b/crates/napi/src/bindgen_runtime/js_values/value_ref.rs index f2e6c5a6..ba937d17 100644 --- a/crates/napi/src/bindgen_runtime/js_values/value_ref.rs +++ b/crates/napi/src/bindgen_runtime/js_values/value_ref.rs @@ -268,7 +268,7 @@ impl SharedReference { let raw = Box::into_raw(Box::new(s)); let prev_drop_fn = unsafe { Box::from_raw(self.owner.finalize_callbacks.get()) }; let drop_fn = Box::new(move || { - unsafe { Box::from_raw(raw) }; + drop(unsafe { Box::from_raw(raw) }); prev_drop_fn(); }); self.owner.finalize_callbacks.set(Box::into_raw(drop_fn)); diff --git a/crates/napi/src/env.rs b/crates/napi/src/env.rs index 2bf13afc..cc8996da 100644 --- a/crates/napi/src/env.rs +++ b/crates/napi/src/env.rs @@ -8,7 +8,7 @@ use std::os::raw::{c_char, c_void}; use std::ptr; use crate::bindgen_runtime::FromNapiValue; -#[cfg(all(feature = "napi4"))] +#[cfg(feature = "napi4")] use crate::bindgen_runtime::ToNapiValue; use crate::{ async_work::{self, AsyncWorkPromise}, @@ -23,15 +23,15 @@ use crate::{ use crate::async_cleanup_hook::AsyncCleanupHook; #[cfg(feature = "napi3")] use crate::cleanup_env::{CleanupEnvHook, CleanupEnvHookData}; -#[cfg(all(feature = "serde-json"))] +#[cfg(feature = "serde-json")] use crate::js_values::{De, Ser}; #[cfg(feature = "napi4")] use crate::threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction}; #[cfg(feature = "napi3")] use crate::JsError; -#[cfg(all(feature = "serde-json"))] +#[cfg(feature = "serde-json")] use serde::de::DeserializeOwned; -#[cfg(all(feature = "serde-json"))] +#[cfg(feature = "serde-json")] use serde::Serialize; pub type Callback = unsafe extern "C" fn(sys::napi_env, sys::napi_callback_info) -> sys::napi_value; @@ -1345,7 +1345,7 @@ pub(crate) unsafe extern "C" fn raw_finalize( finalize_hint: *mut c_void, ) { let tagged_object = finalize_data as *mut TaggedObject; - unsafe { Box::from_raw(tagged_object) }; + drop(unsafe { Box::from_raw(tagged_object) }); if !finalize_hint.is_null() { let size_hint = unsafe { *Box::from_raw(finalize_hint as *mut Option) }; if let Some(changed) = size_hint { diff --git a/crates/napi/src/error.rs b/crates/napi/src/error.rs index 5f701f6a..1d543da2 100644 --- a/crates/napi/src/error.rs +++ b/crates/napi/src/error.rs @@ -1,6 +1,6 @@ use std::convert::{From, TryFrom}; use std::error; -use std::ffi::{CStr, CString}; +use std::ffi::CString; use std::fmt; #[cfg(feature = "serde-json")] use std::fmt::Display; @@ -25,8 +25,7 @@ pub struct Error = Status> { pub status: S, pub reason: String, // Convert raw `JsError` into Error - maybe_raw: sys::napi_ref, - maybe_env: sys::napi_env, + pub(crate) maybe_raw: sys::napi_ref, } impl> ToNapiValue for Error { @@ -36,9 +35,14 @@ impl> ToNapiValue for Error { Ok(err) } else { let mut value = std::ptr::null_mut(); - check_status!(unsafe { - sys::napi_get_reference_value(val.maybe_env, val.maybe_raw, &mut value) - })?; + check_status!( + unsafe { sys::napi_get_reference_value(env, val.maybe_raw, &mut value) }, + "Get error reference in `to_napi_value` failed" + )?; + check_status!( + unsafe { sys::napi_delete_reference(env, val.maybe_raw) }, + "Delete error reference in `to_napi_value` failed" + )?; Ok(value) } } @@ -79,7 +83,7 @@ impl From for Error { impl From for Error { fn from(value: JsUnknown) -> Self { let mut result = std::ptr::null_mut(); - let status = unsafe { sys::napi_create_reference(value.0.env, value.0.value, 0, &mut result) }; + let status = unsafe { sys::napi_create_reference(value.0.env, value.0.value, 1, &mut result) }; if status != sys::Status::napi_ok { return Error::new( Status::from(status), @@ -90,7 +94,6 @@ impl From for Error { status: Status::GenericFailure, reason: "".to_string(), maybe_raw: result, - maybe_env: value.0.env, } } } @@ -118,7 +121,6 @@ impl> Error { status, reason: reason.to_string(), maybe_raw: ptr::null_mut(), - maybe_env: ptr::null_mut(), } } @@ -127,7 +129,6 @@ impl> Error { status, reason: "".to_owned(), maybe_raw: ptr::null_mut(), - maybe_env: ptr::null_mut(), } } } @@ -138,7 +139,6 @@ impl Error { status: Status::GenericFailure, reason: reason.into(), maybe_raw: ptr::null_mut(), - maybe_env: ptr::null_mut(), } } } @@ -149,7 +149,6 @@ impl From for Error { status: Status::GenericFailure, reason: format!("{}", error), maybe_raw: ptr::null_mut(), - maybe_env: ptr::null_mut(), } } } @@ -160,23 +159,6 @@ impl From for Error { status: Status::GenericFailure, reason: format!("{}", error), maybe_raw: ptr::null_mut(), - maybe_env: ptr::null_mut(), - } - } -} - -impl> Drop for Error { - fn drop(&mut self) { - #[cfg(not(feature = "noop"))] - { - if !self.maybe_env.is_null() && !self.maybe_raw.is_null() { - let delete_reference_status = - unsafe { sys::napi_delete_reference(self.maybe_env, self.maybe_raw) }; - debug_assert!( - delete_reference_status == sys::Status::napi_ok, - "Delete Error Reference failed" - ); - } } } } @@ -237,6 +219,11 @@ macro_rules! impl_object_methods { get_err_status == sys::Status::napi_ok, "Get Error from Reference failed" ); + let delete_err_status = unsafe { sys::napi_delete_reference(env, self.0.maybe_raw) }; + debug_assert!( + delete_err_status == sys::Status::napi_ok, + "Delete Error Reference failed" + ); return err; } @@ -289,28 +276,6 @@ macro_rules! impl_object_methods { status ); } - - #[allow(clippy::not_unsafe_ptr_arg_deref)] - pub fn throw(&self, env: sys::napi_env) -> Result<()> { - let error_status = format!("{:?}\0", self.0.status.as_ref()); - let status_len = error_status.len(); - let error_code_string = - unsafe { CStr::from_bytes_with_nul_unchecked(error_status.as_bytes()) }; - let reason_len = self.0.reason.len(); - let reason_c_string = format!("{}\0", self.0.reason.clone()); - let reason = unsafe { CStr::from_bytes_with_nul_unchecked(reason_c_string.as_bytes()) }; - let mut error_code = ptr::null_mut(); - let mut reason_string = ptr::null_mut(); - let mut js_error = ptr::null_mut(); - check_status!(unsafe { - sys::napi_create_string_utf8(env, error_code_string.as_ptr(), status_len, &mut error_code) - })?; - check_status!(unsafe { - sys::napi_create_string_utf8(env, reason.as_ptr(), reason_len, &mut reason_string) - })?; - check_status!(unsafe { $kind(env, error_code, reason_string, &mut js_error) })?; - check_status!(unsafe { sys::napi_throw(env, js_error) }) - } } impl> From> for $js_value { diff --git a/crates/napi/src/js_values/deferred.rs b/crates/napi/src/js_values/deferred.rs index ebcb2e0e..a82e3cca 100644 --- a/crates/napi/src/js_values/deferred.rs +++ b/crates/napi/src/js_values/deferred.rs @@ -4,8 +4,6 @@ use std::os::raw::c_void; use std::ptr; use crate::bindgen_runtime::{ToNapiValue, THREAD_DESTROYED}; -#[cfg(feature = "deferred_trace")] -use crate::JsError; use crate::{check_status, JsObject, Value}; use crate::{sys, Env, Error, Result}; #[cfg(feature = "deferred_trace")] @@ -19,92 +17,73 @@ use crate::{NapiRaw, NapiValue}; /// /// See this issue for more details: /// https://github.com/nodejs/node-addon-api/issues/595 -struct DeferredTrace { - value: sys::napi_ref, - #[cfg(not(feature = "noop"))] - env: sys::napi_env, -} +#[repr(transparent)] +struct DeferredTrace(sys::napi_ref); #[cfg(feature = "deferred_trace")] impl DeferredTrace { - fn new(raw_env: sys::napi_env) -> Self { + fn new(raw_env: sys::napi_env) -> Result { let env = unsafe { Env::from_raw(raw_env) }; let reason = env.create_string("none").unwrap(); let mut js_error = ptr::null_mut(); - let create_error_status = - unsafe { sys::napi_create_error(raw_env, ptr::null_mut(), reason.raw(), &mut js_error) }; - debug_assert!(create_error_status == sys::Status::napi_ok); + check_status!( + unsafe { sys::napi_create_error(raw_env, ptr::null_mut(), reason.raw(), &mut js_error) }, + "Create error in DeferredTrace failed" + )?; let mut result = ptr::null_mut(); - let status = unsafe { sys::napi_create_reference(raw_env, js_error, 1, &mut result) }; - debug_assert!(status == sys::Status::napi_ok); + check_status!( + unsafe { sys::napi_create_reference(raw_env, js_error, 1, &mut result) }, + "Create reference in DeferredTrace failed" + )?; - Self { - value: result, - #[cfg(not(feature = "noop"))] - env: raw_env, - } + Ok(Self(result)) } fn into_rejected(self, raw_env: sys::napi_env, err: Error) -> Result { let env = unsafe { Env::from_raw(raw_env) }; - let raw = unsafe { DeferredTrace::to_napi_value(raw_env, self)? }; + let mut raw = ptr::null_mut(); + check_status!( + unsafe { sys::napi_get_reference_value(raw_env, self.0, &mut raw) }, + "Failed to get referenced value in DeferredTrace" + )?; - let mut obj = unsafe { JsObject::from_raw(raw_env, raw)? }; - if err.reason.is_empty() && err.status == crate::Status::GenericFailure { - // Can't clone err as the clone containing napi pointers will - // be freed when this function returns, causing err to be freed twice. - // Someone should probably fix this. - let err_obj = JsError::from(err).into_unknown(env).coerce_to_object()?; + let mut obj = unsafe { JsObject::from_raw_unchecked(raw_env, raw) }; + let err_value = if !err.maybe_raw.is_null() { + let mut err_raw_value = std::ptr::null_mut(); + check_status!( + unsafe { sys::napi_get_reference_value(raw_env, err.maybe_raw, &mut err_raw_value) }, + "Get error reference in `to_napi_value` failed" + )?; + let err_obj = unsafe { JsObject::from_raw_unchecked(raw_env, err_raw_value) }; - if err_obj.has_named_property("message")? { + let err_value = if err_obj.has_named_property("message")? { // The error was already created inside the JS engine, just return it - Ok(unsafe { JsError::from(Error::from(err_obj.into_unknown())).into_value(raw_env) }) + Ok(unsafe { err_obj.raw() }) } else { obj.set_named_property("message", "")?; obj.set_named_property("code", "")?; Ok(raw) - } + }; + check_status!( + unsafe { sys::napi_delete_reference(raw_env, err.maybe_raw) }, + "Delete error reference in `to_napi_value` failed" + )?; + err_value } else { - obj.set_named_property("message", env.create_string(&err.reason)?)?; - obj.set_named_property("code", env.create_string_from_std(err.status.to_string())?)?; + obj.set_named_property("message", &err.reason)?; + obj.set_named_property( + "code", + env.create_string_from_std(format!("{}", err.status))?, + )?; Ok(raw) - } - } -} - -#[cfg(feature = "deferred_trace")] -impl ToNapiValue for DeferredTrace { - unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { - let mut value = ptr::null_mut(); - check_status!(unsafe { sys::napi_get_reference_value(env, val.value, &mut value) })?; - - if value.is_null() { - // This shouldn't happen but a panic is better than a segfault - Err(Error::new( - crate::Status::GenericFailure, - "Failed to get deferred error reference", - )) - } else { - Ok(value) - } - } -} - -#[cfg(feature = "deferred_trace")] -impl Drop for DeferredTrace { - fn drop(&mut self) { - #[cfg(not(feature = "noop"))] - { - if !self.env.is_null() && !self.value.is_null() { - let delete_reference_status = unsafe { sys::napi_delete_reference(self.env, self.value) }; - debug_assert!( - delete_reference_status == sys::Status::napi_ok, - "Delete Error Reference failed" - ); - } - } + }; + check_status!( + unsafe { sys::napi_delete_reference(raw_env, self.0) }, + "Failed to get referenced value in DeferredTrace" + )?; + err_value } } @@ -138,31 +117,35 @@ impl Result> JsDeferred), - &mut tsfn, - ) - }}?; + check_status!( + unsafe { + sys::napi_create_threadsafe_function( + env, + ptr::null_mut(), + ptr::null_mut(), + async_resource_name, + 0, + 1, + ptr::null_mut(), + None, + raw_deferred.cast(), + Some(napi_resolve_deferred::), + &mut tsfn, + ) + }, + "Create threadsafe function in JsDeferred failed" + )?; let deferred = Self { tsfn, #[cfg(feature = "deferred_trace")] - trace: DeferredTrace::new(env), + trace: DeferredTrace::new(env)?, _data: PhantomData, _resolver: PhantomData, }; @@ -198,13 +181,13 @@ impl Result> JsDeferred Result> JsDeferred return; } } - let deferred = context as sys::napi_deferred; - let deferred_data = unsafe { Box::from_raw(data as *mut DeferredData) }; + let deferred = context.cast(); + let deferred_data: Box> = unsafe { Box::from_raw(data.cast()) }; let result = deferred_data .resolver .and_then(|resolver| resolver(unsafe { Env::from_raw(env) })) .and_then(|res| unsafe { ToNapiValue::to_napi_value(env, res) }); - match result { - Ok(res) => { - let status = unsafe { sys::napi_resolve_deferred(env, deferred, res) }; - debug_assert!( - status == sys::Status::napi_ok, - "Resolve promise failed {:?}", - crate::Status::from(status) - ); - } - Err(e) => { - #[cfg(feature = "deferred_trace")] - let error = deferred_data.trace.into_rejected(env, e).unwrap(); - #[cfg(not(feature = "deferred_trace"))] - let error = unsafe { crate::JsError::from(e).into_value(env) }; + if let Err(e) = result.and_then(|res| { + check_status!( + unsafe { sys::napi_resolve_deferred(env, deferred, res) }, + "Resolve deferred value failed" + ) + }) { + #[cfg(feature = "deferred_trace")] + let error = deferred_data.trace.into_rejected(env, e); + #[cfg(not(feature = "deferred_trace"))] + let error = Ok::(unsafe { crate::JsError::from(e).into_value(env) }); - let status = unsafe { sys::napi_reject_deferred(env, deferred, error) }; - debug_assert!( - status == sys::Status::napi_ok, - "Reject promise failed {:?}", - crate::Status::from(status) - ); + match error { + Ok(error) => { + unsafe { sys::napi_reject_deferred(env, deferred, error) }; + } + Err(err) => { + #[cfg(debug_assertions)] + { + println!("Failed to reject deferred: {:?}", err); + let mut err = ptr::null_mut(); + let mut err_msg = ptr::null_mut(); + unsafe { + sys::napi_create_string_utf8( + env, + "Rejection failed\0".as_ptr().cast(), + 0, + &mut err_msg, + ); + sys::napi_create_error(env, ptr::null_mut(), err_msg, &mut err); + sys::napi_reject_deferred(env, deferred, err); + } + } + } } } } diff --git a/crates/napi/src/js_values/mod.rs b/crates/napi/src/js_values/mod.rs index 29aa4a19..f4e0d8e4 100644 --- a/crates/napi/src/js_values/mod.rs +++ b/crates/napi/src/js_values/mod.rs @@ -337,9 +337,12 @@ macro_rules! impl_object_methods { &mut js_function, ) })?; - check_status!(unsafe { - sys::napi_set_named_property(self.0.env, self.0.value, name.as_ptr(), js_function) - }) + check_status!( + unsafe { + sys::napi_set_named_property(self.0.env, self.0.value, name.as_ptr(), js_function) + }, + "create_named_method error" + ) } pub fn get_named_property(&self, name: &str) -> Result @@ -348,9 +351,12 @@ macro_rules! impl_object_methods { { let key = CString::new(name)?; let mut raw_value = ptr::null_mut(); - check_status!(unsafe { - sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) - })?; + check_status!( + unsafe { + sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) + }, + "get_named_property error" + )?; unsafe { ::from_napi_value(self.0.env, raw_value) } } @@ -360,18 +366,24 @@ macro_rules! impl_object_methods { { let key = CString::new(name)?; let mut raw_value = ptr::null_mut(); - check_status!(unsafe { - sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) - })?; + check_status!( + unsafe { + sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) + }, + "get_named_property_unchecked error" + )?; unsafe { ::from_napi_value(self.0.env, raw_value) } } - pub fn has_named_property(&self, name: &str) -> Result { + pub fn has_named_property>(&self, name: N) -> Result { let mut result = false; - let key = CString::new(name)?; - check_status!(unsafe { - sys::napi_has_named_property(self.0.env, self.0.value, key.as_ptr(), &mut result) - })?; + let key = CString::new(name.as_ref())?; + check_status!( + unsafe { + sys::napi_has_named_property(self.0.env, self.0.value, key.as_ptr(), &mut result) + }, + "napi_has_named_property error" + )?; Ok(result) } diff --git a/crates/napi/src/threadsafe_function.rs b/crates/napi/src/threadsafe_function.rs index 33ba7ee7..65deefe2 100644 --- a/crates/napi/src/threadsafe_function.rs +++ b/crates/napi/src/threadsafe_function.rs @@ -488,26 +488,29 @@ impl ThreadsafeFunction { return Err(crate::Error::from_status(Status::Closing)); } - check_status!(unsafe { - sys::napi_call_threadsafe_function( - self.handle.get_raw(), - Box::into_raw(Box::new(value.map(|data| { - ThreadsafeFunctionCallJsBackData { - data, - call_variant: ThreadsafeFunctionCallVariant::WithCallback, - callback: Box::new(move |d: Result| { - sender - .send(d.and_then(|d| D::from_napi_value(d.0.env, d.0.value))) - .map_err(|_| { - crate::Error::from_reason("Failed to send return value to tokio sender") - }) - }), - } - }))) - .cast(), - ThreadsafeFunctionCallMode::NonBlocking.into(), - ) - }) + check_status!( + unsafe { + sys::napi_call_threadsafe_function( + self.handle.get_raw(), + Box::into_raw(Box::new(value.map(|data| { + ThreadsafeFunctionCallJsBackData { + data, + call_variant: ThreadsafeFunctionCallVariant::WithCallback, + callback: Box::new(move |d: Result| { + sender + .send(d.and_then(|d| D::from_napi_value(d.0.env, d.0.value))) + .map_err(|_| { + crate::Error::from_reason("Failed to send return value to tokio sender") + }) + }), + } + }))) + .cast(), + ThreadsafeFunctionCallMode::NonBlocking.into(), + ) + }, + "Threadsafe function call_async failed" + ) })?; receiver .await @@ -741,11 +744,12 @@ unsafe extern "C" fn call_js_cb( err ); let message_length = message.len(); + let c_message = CString::new(message).unwrap(); unsafe { sys::napi_fatal_error( - "threadsafe_function.rs:720\0".as_ptr().cast(), + "threadsafe_function.rs:749\0".as_ptr().cast(), 26, - CString::new(message).unwrap().into_raw(), + c_message.as_ptr(), message_length, ) }; diff --git a/examples/napi/src/either.rs b/examples/napi/src/either.rs index ac9b1fdd..71bbaa9e 100644 --- a/examples/napi/src/either.rs +++ b/examples/napi/src/either.rs @@ -50,6 +50,7 @@ struct JsClassForEither {} #[napi] impl JsClassForEither { #[napi(constructor)] + #[allow(clippy::new_without_default)] pub fn new() -> Self { JsClassForEither {} } @@ -60,6 +61,7 @@ struct AnotherClassForEither {} #[napi] impl AnotherClassForEither { + #[allow(clippy::new_without_default)] #[napi(constructor)] pub fn new() -> Self { Self {}