mirror of
https://github.com/napi-rs/napi-rs.git
synced 2025-12-08 19:56:07 +00:00
fix!(napi): upgrade to ctor 0.3.6 (#2472)
This commit is contained in:
parent
384dcac588
commit
d96bd288de
4
.github/workflows/test-release.yaml
vendored
4
.github/workflows/test-release.yaml
vendored
@ -260,7 +260,7 @@ jobs:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 22
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install
|
||||
@ -475,7 +475,7 @@ jobs:
|
||||
run: |
|
||||
node -e "console.info('docker-image=${{ matrix.settings.image }}'.replace('{:version}', ${{ matrix.node }}))" >> "$GITHUB_OUTPUT"
|
||||
- name: Run test
|
||||
run: docker run --rm ${{ matrix.settings.args }} -v ${{ github.workspace }}:/build -w /build ${{ steps.image-name.outputs.docker-image }} sh -c "DISABLE_V8_COMPILE_CACHE=1 yarn workspace @examples/napi test -s"
|
||||
run: docker run --rm ${{ matrix.settings.args }} -v ${{ github.workspace }}:/build -w /build ${{ steps.image-name.outputs.docker-image }} sh -c "NODE_OPTIONS=--max-old-space-size=6000 DISABLE_V8_COMPILE_CACHE=1 yarn workspace @examples/napi test -s"
|
||||
|
||||
build-and-test-linux-armv7:
|
||||
name: stable - armv7-unknown-linux-gnueabihf - node@20
|
||||
|
||||
@ -9,7 +9,6 @@ version = "0.1.0"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
ctor = "0.3"
|
||||
napi = { path = "../crates/napi", features = [
|
||||
"tokio_rt",
|
||||
"serde-json",
|
||||
|
||||
@ -36,7 +36,7 @@ impl NapiConst {
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(clippy::all)]
|
||||
#[cfg(all(not(test), not(target_family = "wasm")))]
|
||||
#[napi::bindgen_prelude::ctor]
|
||||
#[napi::ctor::ctor(crate_path=::napi::ctor)]
|
||||
fn #register_name() {
|
||||
napi::bindgen_prelude::register_module_export(#js_mod_ident, #js_name_lit, #cb_name);
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ impl NapiEnum {
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(clippy::all)]
|
||||
#[cfg(all(not(test), not(target_family = "wasm")))]
|
||||
#[napi::bindgen_prelude::ctor]
|
||||
#[napi::ctor::ctor(crate_path=napi::ctor)]
|
||||
fn #register_name() {
|
||||
napi::bindgen_prelude::register_module_export(#js_mod_ident, #js_name_lit, #callback_name);
|
||||
}
|
||||
|
||||
@ -702,7 +702,7 @@ impl NapiFn {
|
||||
#[allow(clippy::all)]
|
||||
#[allow(non_snake_case)]
|
||||
#[cfg(all(not(test), not(target_family = "wasm")))]
|
||||
#[napi::bindgen_prelude::ctor]
|
||||
#[napi::ctor::ctor(crate_path=::napi::ctor)]
|
||||
fn #module_register_name() {
|
||||
napi::bindgen_prelude::register_module_export(#js_mod_ident, #js_name, #cb_name);
|
||||
}
|
||||
|
||||
@ -869,7 +869,7 @@ impl NapiStruct {
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(clippy::all)]
|
||||
#[cfg(all(not(test), not(target_family = "wasm")))]
|
||||
#[napi::bindgen_prelude::ctor]
|
||||
#[napi::ctor::ctor(crate_path=napi::ctor)]
|
||||
fn #struct_register_name() {
|
||||
napi::__private::register_class(std::any::TypeId::of::<#name>(), #js_mod_ident, #js_name, vec![#(#props),*]);
|
||||
}
|
||||
@ -1402,7 +1402,7 @@ impl NapiImpl {
|
||||
#(#methods)*
|
||||
|
||||
#[cfg(all(not(test), not(target_family = "wasm")))]
|
||||
#[napi::bindgen_prelude::ctor]
|
||||
#[napi::ctor::ctor(crate_path=napi::ctor)]
|
||||
fn #register_name() {
|
||||
napi::__private::register_class(std::any::TypeId::of::<#name>(), #js_mod_ident, #js_name, vec![#(#props),*]);
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ pub fn module_exports(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
};
|
||||
|
||||
let register = quote! {
|
||||
#[cfg_attr(not(target_family = "wasm"), napi::bindgen_prelude::ctor)]
|
||||
#[cfg_attr(not(target_family = "wasm"), napi::ctor::ctor(crate_path=napi::ctor))]
|
||||
fn __napi_explicit_module_register() {
|
||||
unsafe fn register(raw_env: napi::sys::napi_env, raw_exports: napi::sys::napi_value) -> napi::Result<()> {
|
||||
use napi::{Env, JsObject, NapiValue};
|
||||
@ -174,3 +174,13 @@ pub fn module_exports(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn module_init(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as ItemFn);
|
||||
quote! {
|
||||
#[napi::ctor::ctor(crate_path=napi::ctor)]
|
||||
#input
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ node_version_detect = []
|
||||
|
||||
[dependencies]
|
||||
bitflags = "2"
|
||||
ctor = "0.3"
|
||||
ctor = "0.3.6"
|
||||
|
||||
[dependencies.anyhow]
|
||||
optional = true
|
||||
|
||||
@ -7,7 +7,7 @@ use std::mem::MaybeUninit;
|
||||
#[cfg(not(feature = "noop"))]
|
||||
use std::ptr;
|
||||
#[cfg(not(feature = "noop"))]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::{LazyLock, RwLock};
|
||||
use std::thread::ThreadId;
|
||||
use std::{any::TypeId, collections::HashMap};
|
||||
@ -52,6 +52,7 @@ impl<K, V> Default for PersistedPerInstanceHashMap<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "noop"))]
|
||||
type ModuleRegisterCallback =
|
||||
RwLock<Vec<(Option<&'static str>, (&'static str, ExportRegisterCallback))>>;
|
||||
|
||||
@ -65,10 +66,12 @@ type FnRegisterMap =
|
||||
PersistedPerInstanceHashMap<ExportRegisterCallback, (sys::napi_callback, &'static str)>;
|
||||
type RegisteredClassesMap = PersistedPerInstanceHashMap<ThreadId, RegisteredClasses>;
|
||||
|
||||
#[cfg(not(feature = "noop"))]
|
||||
static MODULE_REGISTER_CALLBACK: LazyLock<ModuleRegisterCallback> = LazyLock::new(Default::default);
|
||||
#[cfg(not(feature = "noop"))]
|
||||
static MODULE_CLASS_PROPERTIES: LazyLock<ModuleClassProperty> = LazyLock::new(Default::default);
|
||||
#[cfg(not(feature = "noop"))]
|
||||
static IS_FIRST_MODULE: AtomicBool = AtomicBool::new(true);
|
||||
static MODULE_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
#[cfg(not(feature = "noop"))]
|
||||
static FIRST_MODULE_REGISTERED: AtomicBool = AtomicBool::new(false);
|
||||
static REGISTERED_CLASSES: LazyLock<RegisteredClassesMap> = LazyLock::new(Default::default);
|
||||
@ -109,6 +112,7 @@ pub fn register_module_exports(callback: ModuleExportsCallback) {
|
||||
.push(callback);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "noop"))]
|
||||
#[doc(hidden)]
|
||||
pub fn register_module_export(
|
||||
js_mod: Option<&'static str>,
|
||||
@ -142,6 +146,7 @@ pub fn get_class_constructor(js_name: &'static str) -> Option<sys::napi_ref> {
|
||||
})?
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "noop"))]
|
||||
#[doc(hidden)]
|
||||
pub fn register_class(
|
||||
rust_type_id: TypeId,
|
||||
@ -212,10 +217,7 @@ pub unsafe extern "C" fn napi_register_module_v1(
|
||||
env: sys::napi_env,
|
||||
exports: sys::napi_value,
|
||||
) -> sys::napi_value {
|
||||
#[cfg(all(
|
||||
any(target_env = "msvc", feature = "dyn-symbols"),
|
||||
not(feature = "noop")
|
||||
))]
|
||||
#[cfg(any(target_env = "msvc", feature = "dyn-symbols"))]
|
||||
unsafe {
|
||||
sys::setup();
|
||||
}
|
||||
@ -234,11 +236,11 @@ pub unsafe extern "C" fn napi_register_module_v1(
|
||||
NODE_VERSION_PATCH = node_version.patch;
|
||||
};
|
||||
}
|
||||
if IS_FIRST_MODULE.load(Ordering::SeqCst) {
|
||||
IS_FIRST_MODULE.store(false, Ordering::SeqCst);
|
||||
} else {
|
||||
|
||||
if MODULE_COUNT.fetch_add(1, Ordering::SeqCst) != 0 {
|
||||
wait_first_thread_registered();
|
||||
}
|
||||
|
||||
let mut exports_objects: HashSet<String> = HashSet::default();
|
||||
|
||||
{
|
||||
@ -424,29 +426,21 @@ pub unsafe extern "C" fn napi_register_module_v1(
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi4")]
|
||||
let current_thread_id = std::thread::current().id();
|
||||
|
||||
#[cfg(all(not(target_family = "wasm"), feature = "napi3"))]
|
||||
// attach cleanup hook to the `module` object
|
||||
// we don't use the `napi_add_env_cleanup_hook` because it's required napi3
|
||||
check_status_or_throw!(
|
||||
env,
|
||||
unsafe {
|
||||
sys::napi_add_env_cleanup_hook(
|
||||
sys::napi_wrap(
|
||||
env,
|
||||
Some(thread_cleanup),
|
||||
exports,
|
||||
Box::into_raw(Box::new(current_thread_id)).cast(),
|
||||
)
|
||||
},
|
||||
"Failed to add remove thread id cleanup hook"
|
||||
);
|
||||
|
||||
#[cfg(all(target_family = "wasm", feature = "napi3"))]
|
||||
check_status_or_throw!(
|
||||
env,
|
||||
unsafe {
|
||||
crate::napi_add_env_cleanup_hook(
|
||||
env,
|
||||
Some(thread_cleanup),
|
||||
Box::into_raw(Box::new(current_thread_id)).cast(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
)
|
||||
},
|
||||
"Failed to add remove thread id cleanup hook"
|
||||
@ -538,19 +532,24 @@ fn create_custom_gc(env: sys::napi_env, current_thread_id: ThreadId) {
|
||||
THREADS_CAN_ACCESS_ENV.borrow_mut(|m| m.insert(current_thread_id, true));
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "napi3", not(feature = "noop")))]
|
||||
unsafe extern "C" fn thread_cleanup(id: *mut std::ffi::c_void) {
|
||||
let thread_id = unsafe { Box::from_raw(id.cast::<ThreadId>()) };
|
||||
REGISTERED_CLASSES.borrow_mut(|m| {
|
||||
m.remove(&thread_id);
|
||||
});
|
||||
#[cfg(feature = "napi4")]
|
||||
{
|
||||
THREADS_CAN_ACCESS_ENV.borrow_mut(|m| m.remove(&thread_id));
|
||||
#[cfg(feature = "tokio_rt")]
|
||||
#[cfg(not(feature = "noop"))]
|
||||
unsafe extern "C" fn thread_cleanup(
|
||||
_: sys::napi_env,
|
||||
#[allow(unused_variables)] id: *mut std::ffi::c_void,
|
||||
_data: *mut std::ffi::c_void,
|
||||
) {
|
||||
if MODULE_COUNT.fetch_sub(1, Ordering::Relaxed) == 1 {
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
{
|
||||
crate::tokio_runtime::drop_runtime();
|
||||
}
|
||||
crate::bindgen_runtime::REFERENCE_MAP.borrow_mut(|m| m.clear());
|
||||
return;
|
||||
}
|
||||
#[cfg(feature = "napi4")]
|
||||
{
|
||||
let thread_id = unsafe { Box::from_raw(id.cast::<ThreadId>()) };
|
||||
THREADS_CAN_ACCESS_ENV.borrow_mut(|m| m.remove(&thread_id));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//!
|
||||
//! ## Feature flags
|
||||
//!
|
||||
//! ### napi1 ~ napi8
|
||||
//! ### napi1 ~ napi9
|
||||
//!
|
||||
//! Because `Node.js` N-API has versions. So there are feature flags to choose what version of `N-API` you want to build for.
|
||||
//! For example, if you want build a library which can be used by `node@10.17.0`, you should choose the `napi5` or lower.
|
||||
@ -149,8 +149,6 @@ macro_rules! assert_type_of {
|
||||
};
|
||||
}
|
||||
|
||||
pub use crate::bindgen_runtime::ctor as module_init;
|
||||
|
||||
pub mod bindgen_prelude {
|
||||
#[cfg(all(feature = "compat-mode", not(feature = "noop")))]
|
||||
pub use crate::bindgen_runtime::register_module_exports;
|
||||
@ -213,6 +211,8 @@ pub mod __private {
|
||||
}
|
||||
}
|
||||
|
||||
pub extern crate ctor;
|
||||
|
||||
#[cfg(feature = "tokio_rt")]
|
||||
pub extern crate tokio;
|
||||
|
||||
|
||||
@ -62,33 +62,22 @@ pub fn create_custom_tokio_runtime(rt: Runtime) {
|
||||
USER_DEFINED_RT.get_or_init(move || Mutex::new(Some(rt)));
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "noop"))]
|
||||
static RT_REFERENCE_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
|
||||
|
||||
#[cfg(not(feature = "noop"))]
|
||||
/// Ensure that the Tokio runtime is initialized.
|
||||
/// In windows the Tokio runtime will be dropped when Node env exits.
|
||||
/// But in Electron renderer process, the Node env will exits and recreate when the window reloads.
|
||||
/// So we need to ensure that the Tokio runtime is initialized when the Node env is created.
|
||||
pub(crate) fn ensure_runtime() {
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
let mut rt = RT.write().unwrap();
|
||||
if rt.is_none() {
|
||||
*rt = create_runtime();
|
||||
}
|
||||
|
||||
RT_REFERENCE_COUNT.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "noop"))]
|
||||
pub(crate) fn drop_runtime() {
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
if RT_REFERENCE_COUNT.fetch_sub(1, Ordering::AcqRel) == 1 {
|
||||
if let Some(rt) = RT.write().unwrap().take() {
|
||||
rt.shutdown_background();
|
||||
}
|
||||
if let Some(rt) = RT.write().unwrap().take() {
|
||||
rt.shutdown_background();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@ napi3 = ["napi/napi3"]
|
||||
dyn-symbols = ["napi/dyn-symbols"]
|
||||
|
||||
[dependencies]
|
||||
ctor = "0.3"
|
||||
futures = "0.3"
|
||||
napi = { path = "../../crates/napi", features = [
|
||||
"tokio_rt",
|
||||
|
||||
@ -15,7 +15,6 @@ error_try_builds = []
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4"
|
||||
ctor = "0.3"
|
||||
futures = "0.3"
|
||||
bytes = "1"
|
||||
napi-derive = { path = "../../crates/macro", features = ["type-def"] }
|
||||
|
||||
@ -18,7 +18,7 @@ extern crate serde_derive;
|
||||
static ALLOC: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc;
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
#[napi::module_init]
|
||||
#[napi_derive::module_init]
|
||||
fn init() {
|
||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
|
||||
@ -9,7 +9,6 @@ version = "0.1.0"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
ctor = "0.3"
|
||||
futures = "0.3"
|
||||
napi = { path = "../crates/napi", features = [
|
||||
"tokio_rt",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user