refactor(napi): use libloading on Windows

This commit is contained in:
LongYinan 2022-05-06 21:16:35 +08:00
parent 4f120ba8ff
commit 1bf072ad7d
No known key found for this signature in database
GPG key ID: C3666B7FC82ADAD7
24 changed files with 1266 additions and 1157 deletions

View file

@ -150,7 +150,7 @@ export class BuildCommand extends Command {
// https://github.com/napi-rs/napi-rs/issues/297 // https://github.com/napi-rs/napi-rs/issues/297
disableWindowsX32Optimize?: boolean = Option.Boolean( disableWindowsX32Optimize?: boolean = Option.Boolean(
'--disable-windows-x32-optimize', '--disable-windows-x32-optimize',
true, false,
{ {
description: `Disable windows x32 ${chalk.green( description: `Disable windows x32 ${chalk.green(
'lto', 'lto',
@ -262,18 +262,6 @@ export class BuildCommand extends Command {
const intermediateTypeFile = join(tmpdir(), `type_def.${Date.now()}.tmp`) const intermediateTypeFile = join(tmpdir(), `type_def.${Date.now()}.tmp`)
debug(`Run ${chalk.green(cargoCommand)}`) debug(`Run ${chalk.green(cargoCommand)}`)
const additionalEnv = {} const additionalEnv = {}
if (
triple.arch === 'ia32' &&
triple.platform === 'win32' &&
triple.abi === 'msvc' &&
this.disableWindowsX32Optimize
) {
Object.assign(additionalEnv, {
CARGO_PROFILE_DEBUG_CODEGEN_UNITS: 256,
CARGO_PROFILE_RELEASE_CODEGEN_UNITS: 256,
CARGO_PROFILE_RELEASE_LTO: false,
})
}
const rustflags = process.env.RUSTFLAGS const rustflags = process.env.RUSTFLAGS
? process.env.RUSTFLAGS.split(' ') ? process.env.RUSTFLAGS.split(' ')

View file

@ -1,11 +1,9 @@
mod macos; mod macos;
mod windows;
pub fn setup() { pub fn setup() {
println!("cargo:rerun-if-env-changed=DEBUG_GENERATED_CODE"); println!("cargo:rerun-if-env-changed=DEBUG_GENERATED_CODE");
match std::env::var("CARGO_CFG_TARGET_OS").as_deref() { match std::env::var("CARGO_CFG_TARGET_OS").as_deref() {
Ok("macos") => macos::setup(), Ok("macos") => macos::setup(),
Ok("windows") => windows::setup(),
_ => {} _ => {}
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,68 +0,0 @@
#![allow(clippy::expect_fun_call)]
use std::env;
use std::fs::{metadata, write};
use std::path::PathBuf;
fn copy_node_lib(arch: &str) -> Vec<u8> {
match arch {
"x64" => include_bytes!("libs/node-x64.lib").to_vec(),
"x86" => include_bytes!("libs/node-x86.lib").to_vec(),
"arm64" => include_bytes!("libs/node-arm64.lib").to_vec(),
_ => unreachable!(),
}
}
pub fn setup() {
let out_dir = env::var("OUT_DIR").expect("OUT_DIR is not set");
// NPM also gives us an arch var, but let's trust cargo more.
// We translate from cargo's arch env format into npm/gyps's.
// See https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch for rust env values.
// Nodejs appears to follow `process.arch`.
// See https://nodejs.org/docs/latest/api/process.html#process_process_arch for npm env values.
// For windows, we only support `['ia32', 'x64', 'arm64']`
// https://github.com/nodejs/node-gyp/blob/master/lib/install.js#L301
let arch = env::var("CARGO_CFG_TARGET_ARCH")
.map(|arch| match arch.as_str() {
"x86" => "x86",
"x86_64" => "x64",
// https://github.com/nodejs/node/issues/25998
// actually not supported for now
// but we can get it from https://unofficial-builds.nodejs.org/download/release
// just set the `NPM_CONFIG_DISTURL` to `https://unofficial-builds.nodejs.org/download/release`
"aarch64" => "arm64",
arch => panic!("Unsupported CPU Architecture: {}", arch),
})
.expect("Failed to determine target arch");
let mut node_lib_file_path = PathBuf::from(out_dir);
let link_search_dir = node_lib_file_path.clone();
// Encode arch to detect and require node.lib.
let node_lib_file_name = format!("node-{arch}.lib", arch = arch,);
node_lib_file_path.push(&node_lib_file_name);
// If file does not exist, download it.
if metadata(&node_lib_file_path).is_err() {
let node_lib = copy_node_lib(arch);
write(&node_lib_file_path, &node_lib).expect(&format!(
"Could not save file to {}",
node_lib_file_path.to_str().unwrap()
));
}
println!(
"cargo:rustc-link-lib={}",
node_lib_file_path.file_stem().unwrap().to_str().unwrap()
);
println!(
"cargo:rustc-link-search=native={}",
link_search_dir.display()
);
// Link `win_delay_load_hook.obj`
// Needed for electron, but okay for other environments
// https://github.com/neon-bindings/neon/pull/627
println!("cargo:rustc-cdylib-link-arg=delayimp.lib");
println!("cargo:rustc-cdylib-link-arg=/DELAYLOAD:node.exe");
}

View file

@ -49,7 +49,10 @@ tokio_time = ["tokio/time"]
[dependencies] [dependencies]
ctor = "0.1" ctor = "0.1"
lazy_static = "1" lazy_static = "1"
napi-sys = { version = "2.1.0", path = "../sys" }
[dependencies.napi-sys]
version = "2.1.0"
path = "../sys"
[dependencies.encoding_rs] [dependencies.encoding_rs]
optional = true optional = true
@ -71,10 +74,3 @@ version = "1"
[dependencies.serde_json] [dependencies.serde_json]
optional = true optional = true
version = "1" version = "1"
[target.'cfg(windows)'.dependencies]
windows = { version = "0.36", features = [
"Win32_System_WindowsProgramming",
"Win32_System_LibraryLoader",
"Win32_Foundation",
] }

View file

@ -121,10 +121,7 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName {
/// # Safety /// # Safety
/// ///
/// this function called to validate whether napi value passed to rust is valid type /// this function called to validate whether napi value passed to rust is valid type
unsafe fn validate( unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
env: sys::napi_env,
napi_val: sys::napi_value,
) -> Result<napi_sys::napi_value> {
let available_types = Self::type_of(); let available_types = Self::type_of();
if available_types.is_empty() { if available_types.is_empty() {
return Ok(ptr::null_mut()); return Ok(ptr::null_mut());

View file

@ -257,10 +257,7 @@ impl<T> ValidateNapiValue for Vec<T>
where where
T: FromNapiValue, T: FromNapiValue,
{ {
unsafe fn validate( unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
env: sys::napi_env,
napi_val: sys::napi_value,
) -> Result<napi_sys::napi_value> {
let mut is_array = false; let mut is_array = false;
check_status!( check_status!(
unsafe { sys::napi_is_array(env, napi_val, &mut is_array) }, unsafe { sys::napi_is_array(env, napi_val, &mut is_array) },

View file

@ -127,10 +127,7 @@ macro_rules! impl_typed_array {
} }
impl FromNapiValue for $name { impl FromNapiValue for $name {
unsafe fn from_napi_value( unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> Result<Self> {
let mut typed_array_type = 0; let mut typed_array_type = 0;
let mut length = 0; let mut length = 0;
let mut data = ptr::null_mut(); let mut data = ptr::null_mut();

View file

@ -15,12 +15,9 @@ impl TypeName for DateTime<Utc> {
} }
impl ValidateNapiValue for DateTime<Utc> { impl ValidateNapiValue for DateTime<Utc> {
unsafe fn validate( unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
env: sys::napi_env,
napi_val: sys::napi_value,
) -> Result<napi_sys::napi_value> {
let mut is_date = false; let mut is_date = false;
check_status!(unsafe { napi_sys::napi_is_date(env, napi_val, &mut is_date) })?; check_status!(unsafe { sys::napi_is_date(env, napi_val, &mut is_date) })?;
if !is_date { if !is_date {
return Err(Error::new( return Err(Error::new(
Status::InvalidArg, Status::InvalidArg,

View file

@ -1,5 +1,5 @@
use super::{FromNapiValue, ToNapiValue, TypeName}; use super::{FromNapiValue, ToNapiValue, TypeName};
use crate::{type_of, JsNull, JsUndefined, NapiRaw, Status, ValueType}; use crate::{sys, type_of, JsNull, JsUndefined, NapiRaw, Status, ValueType};
const ERROR_MSG: &str = "The return value of typeof(T) should not be equal in Either"; const ERROR_MSG: &str = "The return value of typeof(T) should not be equal in Either";
@ -19,7 +19,7 @@ impl<
{ {
/// # Safety /// # Safety
/// Backward compatible with `Either` in **v1** /// Backward compatible with `Either` in **v1**
pub unsafe fn raw(&self) -> napi_sys::napi_value { pub unsafe fn raw(&self) -> sys::napi_value {
match &self { match &self {
Self::A(a) => unsafe { a.raw() }, Self::A(a) => unsafe { a.raw() },
Self::B(b) => unsafe { b.raw() }, Self::B(b) => unsafe { b.raw() },
@ -61,10 +61,7 @@ impl<T: TypeName + FromNapiValue + ToNapiValue> From<Either<T, JsNull>> for Opti
impl<A: TypeName + FromNapiValue + ToNapiValue, B: TypeName + FromNapiValue + ToNapiValue> impl<A: TypeName + FromNapiValue + ToNapiValue, B: TypeName + FromNapiValue + ToNapiValue>
FromNapiValue for Either<A, B> FromNapiValue for Either<A, B>
{ {
unsafe fn from_napi_value( unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> crate::Result<Self> {
debug_assert!(A::value_type() != B::value_type(), "{}", ERROR_MSG); debug_assert!(A::value_type() != B::value_type(), "{}", ERROR_MSG);
let js_type = type_of!(env, napi_val)?; let js_type = type_of!(env, napi_val)?;
if js_type == A::value_type() { if js_type == A::value_type() {
@ -89,7 +86,7 @@ impl<A: TypeName + FromNapiValue + ToNapiValue, B: TypeName + FromNapiValue + To
ToNapiValue for Either<A, B> ToNapiValue for Either<A, B>
{ {
unsafe fn to_napi_value( unsafe fn to_napi_value(
env: napi_sys::napi_env, env: sys::napi_env,
value: Self, value: Self,
) -> crate::Result<crate::sys::napi_value> { ) -> crate::Result<crate::sys::napi_value> {
match value { match value {
@ -131,10 +128,7 @@ impl<
C: TypeName + FromNapiValue + ToNapiValue, C: TypeName + FromNapiValue + ToNapiValue,
> FromNapiValue for Either3<A, B, C> > FromNapiValue for Either3<A, B, C>
{ {
unsafe fn from_napi_value( unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> crate::Result<Self> {
debug_assert!( debug_assert!(
{ {
let mut types = vec![A::value_type(), B::value_type(), C::value_type()]; let mut types = vec![A::value_type(), B::value_type(), C::value_type()];
@ -173,7 +167,7 @@ impl<
> ToNapiValue for Either3<A, B, C> > ToNapiValue for Either3<A, B, C>
{ {
unsafe fn to_napi_value( unsafe fn to_napi_value(
env: napi_sys::napi_env, env: sys::napi_env,
value: Self, value: Self,
) -> crate::Result<crate::sys::napi_value> { ) -> crate::Result<crate::sys::napi_value> {
match value { match value {
@ -220,10 +214,7 @@ impl<
D: TypeName + FromNapiValue + ToNapiValue, D: TypeName + FromNapiValue + ToNapiValue,
> FromNapiValue for Either4<A, B, C, D> > FromNapiValue for Either4<A, B, C, D>
{ {
unsafe fn from_napi_value( unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> crate::Result<Self> {
debug_assert!( debug_assert!(
{ {
let mut types = vec![ let mut types = vec![
@ -271,7 +262,7 @@ impl<
> ToNapiValue for Either4<A, B, C, D> > ToNapiValue for Either4<A, B, C, D>
{ {
unsafe fn to_napi_value( unsafe fn to_napi_value(
env: napi_sys::napi_env, env: sys::napi_env,
value: Self, value: Self,
) -> crate::Result<crate::sys::napi_value> { ) -> crate::Result<crate::sys::napi_value> {
match value { match value {
@ -323,10 +314,7 @@ impl<
E: TypeName + FromNapiValue + ToNapiValue, E: TypeName + FromNapiValue + ToNapiValue,
> FromNapiValue for Either5<A, B, C, D, E> > FromNapiValue for Either5<A, B, C, D, E>
{ {
unsafe fn from_napi_value( unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> crate::Result<Self> {
debug_assert!( debug_assert!(
{ {
let mut types = vec![ let mut types = vec![
@ -379,7 +367,7 @@ impl<
> ToNapiValue for Either5<A, B, C, D, E> > ToNapiValue for Either5<A, B, C, D, E>
{ {
unsafe fn to_napi_value( unsafe fn to_napi_value(
env: napi_sys::napi_env, env: sys::napi_env,
value: Self, value: Self,
) -> crate::Result<crate::sys::napi_value> { ) -> crate::Result<crate::sys::napi_value> {
match value { match value {

View file

@ -3,7 +3,7 @@ use std::{
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
use crate::{check_status, Error, Status, TaggedObject}; use crate::{check_status, sys, Error, Status, TaggedObject};
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue}; use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
@ -53,13 +53,10 @@ impl<T: 'static> External<T> {
} }
impl<T: 'static> FromNapiValue for External<T> { impl<T: 'static> FromNapiValue for External<T> {
unsafe fn from_napi_value( unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> crate::Result<Self> {
let mut unknown_tagged_object = std::ptr::null_mut(); let mut unknown_tagged_object = std::ptr::null_mut();
check_status!( check_status!(
unsafe { napi_sys::napi_get_value_external(env, napi_val, &mut unknown_tagged_object) }, unsafe { sys::napi_get_value_external(env, napi_val, &mut unknown_tagged_object) },
"Failed to get external value" "Failed to get external value"
)?; )?;
@ -107,14 +104,11 @@ impl<T: 'static> DerefMut for External<T> {
} }
impl<T: 'static> ToNapiValue for External<T> { impl<T: 'static> ToNapiValue for External<T> {
unsafe fn to_napi_value( unsafe fn to_napi_value(env: sys::napi_env, mut val: Self) -> crate::Result<sys::napi_value> {
env: napi_sys::napi_env,
mut val: Self,
) -> crate::Result<napi_sys::napi_value> {
let mut napi_value = std::ptr::null_mut(); let mut napi_value = std::ptr::null_mut();
check_status!( check_status!(
unsafe { unsafe {
napi_sys::napi_create_external( sys::napi_create_external(
env, env,
val.obj as *mut _, val.obj as *mut _,
Some(crate::raw_finalize::<T>), Some(crate::raw_finalize::<T>),
@ -130,7 +124,7 @@ impl<T: 'static> ToNapiValue for External<T> {
if val.size_hint != 0 { if val.size_hint != 0 {
check_status!( check_status!(
unsafe { unsafe {
napi_sys::napi_adjust_external_memory( sys::napi_adjust_external_memory(
env, env,
val.size_hint as i64, val.size_hint as i64,
adjusted_external_memory_size.as_mut_ptr(), adjusted_external_memory_size.as_mut_ptr(),

View file

@ -6,7 +6,7 @@ use std::task::{Context, Poll};
use tokio::sync::oneshot::{channel, Receiver, Sender}; use tokio::sync::oneshot::{channel, Receiver, Sender};
use crate::{check_status, Error, Result, Status}; use crate::{check_status, sys, Error, Result, Status};
use super::{FromNapiValue, TypeName, ValidateNapiValue}; use super::{FromNapiValue, TypeName, ValidateNapiValue};
@ -32,7 +32,7 @@ impl<T: FromNapiValue> ValidateNapiValue for Promise<T> {
unsafe fn validate( unsafe fn validate(
env: crate::sys::napi_env, env: crate::sys::napi_env,
napi_val: crate::sys::napi_value, napi_val: crate::sys::napi_value,
) -> Result<napi_sys::napi_value> { ) -> Result<sys::napi_value> {
let mut is_promise = false; let mut is_promise = false;
check_status!( check_status!(
unsafe { crate::sys::napi_is_promise(env, napi_val, &mut is_promise) }, unsafe { crate::sys::napi_is_promise(env, napi_val, &mut is_promise) },
@ -84,16 +84,11 @@ impl<T: FromNapiValue> ValidateNapiValue for Promise<T> {
unsafe impl<T: FromNapiValue> Send for Promise<T> {} unsafe impl<T: FromNapiValue> Send for Promise<T> {}
impl<T: FromNapiValue> FromNapiValue for Promise<T> { impl<T: FromNapiValue> FromNapiValue for Promise<T> {
unsafe fn from_napi_value( unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> crate::Result<Self> {
let mut then = ptr::null_mut(); let mut then = ptr::null_mut();
let then_c_string = unsafe { CStr::from_bytes_with_nul_unchecked(b"then\0") }; let then_c_string = unsafe { CStr::from_bytes_with_nul_unchecked(b"then\0") };
check_status!( check_status!(
unsafe { unsafe { sys::napi_get_named_property(env, napi_val, then_c_string.as_ptr(), &mut then) },
napi_sys::napi_get_named_property(env, napi_val, then_c_string.as_ptr(), &mut then)
},
"Failed to get then function" "Failed to get then function"
)?; )?;
let mut promise_after_then = ptr::null_mut(); let mut promise_after_then = ptr::null_mut();
@ -102,7 +97,7 @@ impl<T: FromNapiValue> FromNapiValue for Promise<T> {
let tx_ptr = Box::into_raw(Box::new(tx)); let tx_ptr = Box::into_raw(Box::new(tx));
check_status!( check_status!(
unsafe { unsafe {
napi_sys::napi_create_function( sys::napi_create_function(
env, env,
then_c_string.as_ptr(), then_c_string.as_ptr(),
4, 4,
@ -115,7 +110,7 @@ impl<T: FromNapiValue> FromNapiValue for Promise<T> {
)?; )?;
check_status!( check_status!(
unsafe { unsafe {
napi_sys::napi_call_function( sys::napi_call_function(
env, env,
napi_val, napi_val,
then, then,
@ -130,19 +125,14 @@ impl<T: FromNapiValue> FromNapiValue for Promise<T> {
let catch_c_string = unsafe { CStr::from_bytes_with_nul_unchecked(b"catch\0") }; let catch_c_string = unsafe { CStr::from_bytes_with_nul_unchecked(b"catch\0") };
check_status!( check_status!(
unsafe { unsafe {
napi_sys::napi_get_named_property( sys::napi_get_named_property(env, promise_after_then, catch_c_string.as_ptr(), &mut catch)
env,
promise_after_then,
catch_c_string.as_ptr(),
&mut catch,
)
}, },
"Failed to get then function" "Failed to get then function"
)?; )?;
let mut catch_js_cb = ptr::null_mut(); let mut catch_js_cb = ptr::null_mut();
check_status!( check_status!(
unsafe { unsafe {
napi_sys::napi_create_function( sys::napi_create_function(
env, env,
catch_c_string.as_ptr(), catch_c_string.as_ptr(),
5, 5,
@ -155,7 +145,7 @@ impl<T: FromNapiValue> FromNapiValue for Promise<T> {
)?; )?;
check_status!( check_status!(
unsafe { unsafe {
napi_sys::napi_call_function( sys::napi_call_function(
env, env,
promise_after_then, promise_after_then,
catch, catch,
@ -187,14 +177,14 @@ impl<T: FromNapiValue> future::Future for Promise<T> {
} }
unsafe extern "C" fn then_callback<T: FromNapiValue>( unsafe extern "C" fn then_callback<T: FromNapiValue>(
env: napi_sys::napi_env, env: sys::napi_env,
info: napi_sys::napi_callback_info, info: sys::napi_callback_info,
) -> napi_sys::napi_value { ) -> sys::napi_value {
let mut data = ptr::null_mut(); let mut data = ptr::null_mut();
let mut resolved_value: [napi_sys::napi_value; 1] = [ptr::null_mut()]; let mut resolved_value: [sys::napi_value; 1] = [ptr::null_mut()];
let mut this = ptr::null_mut(); let mut this = ptr::null_mut();
let get_cb_status = unsafe { let get_cb_status = unsafe {
napi_sys::napi_get_cb_info( sys::napi_get_cb_info(
env, env,
info, info,
&mut 1, &mut 1,
@ -204,7 +194,7 @@ unsafe extern "C" fn then_callback<T: FromNapiValue>(
) )
}; };
debug_assert!( debug_assert!(
get_cb_status == napi_sys::Status::napi_ok, get_cb_status == sys::Status::napi_ok,
"Get callback info from Promise::then failed" "Get callback info from Promise::then failed"
); );
let resolve_value_t = Box::new(unsafe { T::from_napi_value(env, resolved_value[0]) }); let resolve_value_t = Box::new(unsafe { T::from_napi_value(env, resolved_value[0]) });
@ -216,15 +206,15 @@ unsafe extern "C" fn then_callback<T: FromNapiValue>(
} }
unsafe extern "C" fn catch_callback<T: FromNapiValue>( unsafe extern "C" fn catch_callback<T: FromNapiValue>(
env: napi_sys::napi_env, env: sys::napi_env,
info: napi_sys::napi_callback_info, info: sys::napi_callback_info,
) -> napi_sys::napi_value { ) -> sys::napi_value {
let mut data = ptr::null_mut(); let mut data = ptr::null_mut();
let mut rejected_value: [napi_sys::napi_value; 1] = [ptr::null_mut()]; let mut rejected_value: [sys::napi_value; 1] = [ptr::null_mut()];
let mut this = ptr::null_mut(); let mut this = ptr::null_mut();
let mut argc = 1; let mut argc = 1;
let get_cb_status = unsafe { let get_cb_status = unsafe {
napi_sys::napi_get_cb_info( sys::napi_get_cb_info(
env, env,
info, info,
&mut argc, &mut argc,
@ -234,15 +224,15 @@ unsafe extern "C" fn catch_callback<T: FromNapiValue>(
) )
}; };
debug_assert!( debug_assert!(
get_cb_status == napi_sys::Status::napi_ok, get_cb_status == sys::Status::napi_ok,
"Get callback info from Promise::catch failed" "Get callback info from Promise::catch failed"
); );
let rejected_value = rejected_value[0]; let rejected_value = rejected_value[0];
let mut error_ref = ptr::null_mut(); let mut error_ref = ptr::null_mut();
let create_ref_status = let create_ref_status =
unsafe { napi_sys::napi_create_reference(env, rejected_value, 1, &mut error_ref) }; unsafe { sys::napi_create_reference(env, rejected_value, 1, &mut error_ref) };
debug_assert!( debug_assert!(
create_ref_status == napi_sys::Status::napi_ok, create_ref_status == sys::Status::napi_ok,
"Create Error reference failed" "Create Error reference failed"
); );
let sender = unsafe { Box::from_raw(data as *mut Sender<*mut Result<T>>) }; let sender = unsafe { Box::from_raw(data as *mut Sender<*mut Result<T>>) };

View file

@ -1,6 +1,6 @@
use std::{ffi::CString, ptr}; use std::{ffi::CString, ptr};
use crate::check_status; use crate::{check_status, sys};
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue}; use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
@ -35,20 +35,17 @@ impl Symbol {
} }
impl ToNapiValue for Symbol { impl ToNapiValue for Symbol {
unsafe fn to_napi_value( unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
env: napi_sys::napi_env,
val: Self,
) -> crate::Result<napi_sys::napi_value> {
let mut symbol_value = ptr::null_mut(); let mut symbol_value = ptr::null_mut();
check_status!(unsafe { check_status!(unsafe {
napi_sys::napi_create_symbol( sys::napi_create_symbol(
env, env,
match val.desc { match val.desc {
Some(desc) => { Some(desc) => {
let mut desc_string = ptr::null_mut(); let mut desc_string = ptr::null_mut();
let desc_len = desc.len(); let desc_len = desc.len();
let desc_c_string = CString::new(desc)?; let desc_c_string = CString::new(desc)?;
check_status!(napi_sys::napi_create_string_utf8( check_status!(sys::napi_create_string_utf8(
env, env,
desc_c_string.as_ptr(), desc_c_string.as_ptr(),
desc_len, desc_len,
@ -67,8 +64,8 @@ impl ToNapiValue for Symbol {
impl FromNapiValue for Symbol { impl FromNapiValue for Symbol {
unsafe fn from_napi_value( unsafe fn from_napi_value(
_env: napi_sys::napi_env, _env: sys::napi_env,
_napi_val: napi_sys::napi_value, _napi_val: sys::napi_value,
) -> crate::Result<Self> { ) -> crate::Result<Self> {
Ok(Self { desc: None }) Ok(Self { desc: None })
} }

View file

@ -4,7 +4,9 @@ use std::rc::Rc;
use std::sync::atomic::{AtomicPtr, AtomicU8, Ordering}; use std::sync::atomic::{AtomicPtr, AtomicU8, Ordering};
use super::{FromNapiValue, ToNapiValue, TypeName}; use super::{FromNapiValue, ToNapiValue, TypeName};
use crate::{async_work, check_status, Env, Error, JsError, JsObject, NapiValue, Status, Task}; use crate::{
async_work, check_status, sys, Env, Error, JsError, JsObject, NapiValue, Status, Task,
};
pub struct AsyncTask<T: Task> { pub struct AsyncTask<T: Task> {
inner: T, inner: T,
@ -46,21 +48,17 @@ impl<T: Task> AsyncTask<T> {
/// <https://developer.mozilla.org/zh-CN/docs/Web/API/AbortController> /// <https://developer.mozilla.org/zh-CN/docs/Web/API/AbortController>
pub struct AbortSignal { pub struct AbortSignal {
raw_work: Rc<AtomicPtr<napi_sys::napi_async_work__>>, raw_work: Rc<AtomicPtr<sys::napi_async_work__>>,
raw_deferred: Rc<AtomicPtr<napi_sys::napi_deferred__>>, raw_deferred: Rc<AtomicPtr<sys::napi_deferred__>>,
status: Rc<AtomicU8>, status: Rc<AtomicU8>,
} }
impl FromNapiValue for AbortSignal { impl FromNapiValue for AbortSignal {
unsafe fn from_napi_value( unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
env: napi_sys::napi_env,
napi_val: napi_sys::napi_value,
) -> crate::Result<Self> {
let mut signal = unsafe { JsObject::from_raw_unchecked(env, napi_val) }; let mut signal = unsafe { JsObject::from_raw_unchecked(env, napi_val) };
let async_work_inner: Rc<AtomicPtr<napi_sys::napi_async_work__>> = let async_work_inner: Rc<AtomicPtr<sys::napi_async_work__>> =
Rc::new(AtomicPtr::new(ptr::null_mut()));
let raw_promise: Rc<AtomicPtr<napi_sys::napi_deferred__>> =
Rc::new(AtomicPtr::new(ptr::null_mut())); Rc::new(AtomicPtr::new(ptr::null_mut()));
let raw_promise: Rc<AtomicPtr<sys::napi_deferred__>> = Rc::new(AtomicPtr::new(ptr::null_mut()));
let task_status = Rc::new(AtomicU8::new(0)); let task_status = Rc::new(AtomicU8::new(0));
let abort_controller = AbortSignal { let abort_controller = AbortSignal {
raw_work: async_work_inner.clone(), raw_work: async_work_inner.clone(),
@ -69,7 +67,7 @@ impl FromNapiValue for AbortSignal {
}; };
let js_env = unsafe { Env::from_raw(env) }; let js_env = unsafe { Env::from_raw(env) };
check_status!(unsafe { check_status!(unsafe {
napi_sys::napi_wrap( sys::napi_wrap(
env, env,
signal.0.value, signal.0.value,
Box::into_raw(Box::new(abort_controller)) as *mut _, Box::into_raw(Box::new(abort_controller)) as *mut _,
@ -88,12 +86,12 @@ impl FromNapiValue for AbortSignal {
} }
extern "C" fn on_abort( extern "C" fn on_abort(
env: napi_sys::napi_env, env: sys::napi_env,
callback_info: napi_sys::napi_callback_info, callback_info: sys::napi_callback_info,
) -> napi_sys::napi_value { ) -> sys::napi_value {
let mut this = ptr::null_mut(); let mut this = ptr::null_mut();
unsafe { unsafe {
let get_cb_info_status = napi_sys::napi_get_cb_info( let get_cb_info_status = sys::napi_get_cb_info(
env, env,
callback_info, callback_info,
&mut 0, &mut 0,
@ -103,15 +101,15 @@ extern "C" fn on_abort(
); );
debug_assert_eq!( debug_assert_eq!(
get_cb_info_status, get_cb_info_status,
napi_sys::Status::napi_ok, sys::Status::napi_ok,
"{}", "{}",
"Get callback info in AbortController abort callback failed" "Get callback info in AbortController abort callback failed"
); );
let mut async_task = ptr::null_mut(); let mut async_task = ptr::null_mut();
let status = napi_sys::napi_unwrap(env, this, &mut async_task); let status = sys::napi_unwrap(env, this, &mut async_task);
debug_assert_eq!( debug_assert_eq!(
status, status,
napi_sys::Status::napi_ok, sys::Status::napi_ok,
"{}", "{}",
"Unwrap async_task from AbortSignal failed" "Unwrap async_task from AbortSignal failed"
); );
@ -122,15 +120,15 @@ extern "C" fn on_abort(
} }
let raw_async_work = abort_controller.raw_work.load(Ordering::Relaxed); let raw_async_work = abort_controller.raw_work.load(Ordering::Relaxed);
let deferred = abort_controller.raw_deferred.load(Ordering::Relaxed); let deferred = abort_controller.raw_deferred.load(Ordering::Relaxed);
napi_sys::napi_cancel_async_work(env, raw_async_work); sys::napi_cancel_async_work(env, raw_async_work);
// abort function must be called from JavaScript main thread, so Relaxed Ordering is ok. // abort function must be called from JavaScript main thread, so Relaxed Ordering is ok.
abort_controller.status.store(2, Ordering::Relaxed); abort_controller.status.store(2, Ordering::Relaxed);
let abort_error = Error::new(Status::Cancelled, "AbortError".to_owned()); let abort_error = Error::new(Status::Cancelled, "AbortError".to_owned());
let reject_status = let reject_status =
napi_sys::napi_reject_deferred(env, deferred, JsError::from(abort_error).into_value(env)); sys::napi_reject_deferred(env, deferred, JsError::from(abort_error).into_value(env));
debug_assert_eq!( debug_assert_eq!(
reject_status, reject_status,
napi_sys::Status::napi_ok, sys::Status::napi_ok,
"{}", "{}",
"Reject AbortError failed" "Reject AbortError failed"
); );
@ -139,10 +137,7 @@ extern "C" fn on_abort(
} }
impl<T: Task> ToNapiValue for AsyncTask<T> { impl<T: Task> ToNapiValue for AsyncTask<T> {
unsafe fn to_napi_value( unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> crate::Result<sys::napi_value> {
env: napi_sys::napi_env,
val: Self,
) -> crate::Result<napi_sys::napi_value> {
if let Some(abort_controller) = val.abort_signal { if let Some(abort_controller) = val.abort_signal {
let async_promise = async_work::run(env, val.inner, Some(abort_controller.status.clone()))?; let async_promise = async_work::run(env, val.inner, Some(abort_controller.status.clone()))?;
abort_controller abort_controller
@ -160,7 +155,7 @@ impl<T: Task> ToNapiValue for AsyncTask<T> {
} }
unsafe extern "C" fn async_task_abort_controller_finalize( unsafe extern "C" fn async_task_abort_controller_finalize(
_env: napi_sys::napi_env, _env: sys::napi_env,
finalize_data: *mut c_void, finalize_data: *mut c_void,
_finalize_hint: *mut c_void, _finalize_hint: *mut c_void,
) { ) {

View file

@ -21,7 +21,7 @@ impl TypeName for JsDate {
impl ValidateNapiValue for JsDate { impl ValidateNapiValue for JsDate {
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> { unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
let mut is_date = false; let mut is_date = false;
check_status!(unsafe { napi_sys::napi_is_date(env, napi_val, &mut is_date) })?; check_status!(unsafe { sys::napi_is_date(env, napi_val, &mut is_date) })?;
if !is_date { if !is_date {
return Err(Error::new( return Err(Error::new(
Status::InvalidArg, Status::InvalidArg,

View file

@ -100,8 +100,6 @@ pub use cleanup_env::CleanupEnvHook;
pub mod threadsafe_function; pub mod threadsafe_function;
mod version; mod version;
#[cfg(target_os = "windows")]
mod win_delay_load_hook;
pub use napi_sys as sys; pub use napi_sys as sys;

View file

@ -23,3 +23,9 @@ napi8 = ["napi7"]
[package.metadata.workspaces] [package.metadata.workspaces]
independent = true independent = true
[target.'cfg(windows)'.dependencies.libloading]
version = "0.7"
[target.'cfg(windows)'.dependencies.ctor]
version = "0.1"

41
crates/sys/LICENSE Normal file
View file

@ -0,0 +1,41 @@
MIT License
Copyright (c) 2020-present LongYinan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Copyright (c) 2015 David Herman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -1,5 +1,7 @@
# napi-sys # napi-sys
Dynamic loading logic copied from https://github.com/neon-bindings/neon/tree/0.10.0/crates/neon-runtime/src/napi/bindings.
<a href="https://docs.rs/crate/napi-sys"><img src="https://docs.rs/napi-sys/badge.svg"></img></a> <a href="https://docs.rs/crate/napi-sys"><img src="https://docs.rs/napi-sys/badge.svg"></img></a>
<a href="https://crates.io/crates/napi-sys"><img src="https://img.shields.io/crates/v/napi-sys.svg"></img></a> <a href="https://crates.io/crates/napi-sys"><img src="https://img.shields.io/crates/v/napi-sys.svg"></img></a>
<a href="https://discord.gg/SpWzYHsKHs"> <a href="https://discord.gg/SpWzYHsKHs">

765
crates/sys/src/functions.rs Normal file
View file

@ -0,0 +1,765 @@
#![allow(clippy::too_many_arguments)]
mod napi1 {
use super::super::types::*;
use std::os::raw::{c_char, c_void};
generate!(
extern "C" {
fn napi_get_last_error_info(
env: napi_env,
result: *mut *const napi_extended_error_info,
) -> napi_status;
fn napi_get_undefined(env: napi_env, result: *mut napi_value) -> napi_status;
fn napi_get_null(env: napi_env, result: *mut napi_value) -> napi_status;
fn napi_get_global(env: napi_env, result: *mut napi_value) -> napi_status;
fn napi_get_boolean(env: napi_env, value: bool, result: *mut napi_value) -> napi_status;
fn napi_create_object(env: napi_env, result: *mut napi_value) -> napi_status;
fn napi_create_array(env: napi_env, result: *mut napi_value) -> napi_status;
fn napi_create_array_with_length(
env: napi_env,
length: usize,
result: *mut napi_value,
) -> napi_status;
fn napi_create_double(env: napi_env, value: f64, result: *mut napi_value) -> napi_status;
fn napi_create_int32(env: napi_env, value: i32, result: *mut napi_value) -> napi_status;
fn napi_create_uint32(env: napi_env, value: u32, result: *mut napi_value) -> napi_status;
fn napi_create_int64(env: napi_env, value: i64, result: *mut napi_value) -> napi_status;
fn napi_create_string_latin1(
env: napi_env,
str_: *const c_char,
length: usize,
result: *mut napi_value,
) -> napi_status;
fn napi_create_string_utf8(
env: napi_env,
str_: *const c_char,
length: usize,
result: *mut napi_value,
) -> napi_status;
fn napi_create_string_utf16(
env: napi_env,
str_: *const u16,
length: usize,
result: *mut napi_value,
) -> napi_status;
fn napi_create_symbol(
env: napi_env,
description: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_create_function(
env: napi_env,
utf8name: *const c_char,
length: usize,
cb: napi_callback,
data: *mut c_void,
result: *mut napi_value,
) -> napi_status;
fn napi_create_error(
env: napi_env,
code: napi_value,
msg: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_create_type_error(
env: napi_env,
code: napi_value,
msg: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_create_range_error(
env: napi_env,
code: napi_value,
msg: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_typeof(env: napi_env, value: napi_value, result: *mut napi_valuetype) -> napi_status;
fn napi_get_value_double(env: napi_env, value: napi_value, result: *mut f64) -> napi_status;
fn napi_get_value_int32(env: napi_env, value: napi_value, result: *mut i32) -> napi_status;
fn napi_get_value_uint32(env: napi_env, value: napi_value, result: *mut u32) -> napi_status;
fn napi_get_value_int64(env: napi_env, value: napi_value, result: *mut i64) -> napi_status;
fn napi_get_value_bool(env: napi_env, value: napi_value, result: *mut bool) -> napi_status;
fn napi_get_value_string_latin1(
env: napi_env,
value: napi_value,
buf: *mut c_char,
bufsize: usize,
result: *mut usize,
) -> napi_status;
fn napi_get_value_string_utf8(
env: napi_env,
value: napi_value,
buf: *mut c_char,
bufsize: usize,
result: *mut usize,
) -> napi_status;
fn napi_get_value_string_utf16(
env: napi_env,
value: napi_value,
buf: *mut u16,
bufsize: usize,
result: *mut usize,
) -> napi_status;
fn napi_coerce_to_bool(
env: napi_env,
value: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_coerce_to_number(
env: napi_env,
value: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_coerce_to_object(
env: napi_env,
value: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_coerce_to_string(
env: napi_env,
value: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_get_prototype(
env: napi_env,
object: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_get_property_names(
env: napi_env,
object: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_set_property(
env: napi_env,
object: napi_value,
key: napi_value,
value: napi_value,
) -> napi_status;
fn napi_has_property(
env: napi_env,
object: napi_value,
key: napi_value,
result: *mut bool,
) -> napi_status;
fn napi_get_property(
env: napi_env,
object: napi_value,
key: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_delete_property(
env: napi_env,
object: napi_value,
key: napi_value,
result: *mut bool,
) -> napi_status;
fn napi_has_own_property(
env: napi_env,
object: napi_value,
key: napi_value,
result: *mut bool,
) -> napi_status;
fn napi_set_named_property(
env: napi_env,
object: napi_value,
utf8name: *const c_char,
value: napi_value,
) -> napi_status;
fn napi_has_named_property(
env: napi_env,
object: napi_value,
utf8name: *const c_char,
result: *mut bool,
) -> napi_status;
fn napi_get_named_property(
env: napi_env,
object: napi_value,
utf8name: *const c_char,
result: *mut napi_value,
) -> napi_status;
fn napi_set_element(
env: napi_env,
object: napi_value,
index: u32,
value: napi_value,
) -> napi_status;
fn napi_has_element(
env: napi_env,
object: napi_value,
index: u32,
result: *mut bool,
) -> napi_status;
fn napi_get_element(
env: napi_env,
object: napi_value,
index: u32,
result: *mut napi_value,
) -> napi_status;
fn napi_delete_element(
env: napi_env,
object: napi_value,
index: u32,
result: *mut bool,
) -> napi_status;
fn napi_define_properties(
env: napi_env,
object: napi_value,
property_count: usize,
properties: *const napi_property_descriptor,
) -> napi_status;
fn napi_is_array(env: napi_env, value: napi_value, result: *mut bool) -> napi_status;
fn napi_get_array_length(env: napi_env, value: napi_value, result: *mut u32) -> napi_status;
fn napi_strict_equals(
env: napi_env,
lhs: napi_value,
rhs: napi_value,
result: *mut bool,
) -> napi_status;
fn napi_call_function(
env: napi_env,
recv: napi_value,
func: napi_value,
argc: usize,
argv: *const napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_new_instance(
env: napi_env,
constructor: napi_value,
argc: usize,
argv: *const napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_instanceof(
env: napi_env,
object: napi_value,
constructor: napi_value,
result: *mut bool,
) -> napi_status;
fn napi_get_cb_info(
env: napi_env,
cbinfo: napi_callback_info,
argc: *mut usize,
argv: *mut napi_value,
this_arg: *mut napi_value,
data: *mut *mut c_void,
) -> napi_status;
fn napi_get_new_target(
env: napi_env,
cbinfo: napi_callback_info,
result: *mut napi_value,
) -> napi_status;
fn napi_define_class(
env: napi_env,
utf8name: *const c_char,
length: usize,
constructor: napi_callback,
data: *mut c_void,
property_count: usize,
properties: *const napi_property_descriptor,
result: *mut napi_value,
) -> napi_status;
fn napi_wrap(
env: napi_env,
js_object: napi_value,
native_object: *mut c_void,
finalize_cb: napi_finalize,
finalize_hint: *mut c_void,
result: *mut napi_ref,
) -> napi_status;
fn napi_unwrap(env: napi_env, js_object: napi_value, result: *mut *mut c_void)
-> napi_status;
fn napi_remove_wrap(
env: napi_env,
js_object: napi_value,
result: *mut *mut c_void,
) -> napi_status;
fn napi_create_external(
env: napi_env,
data: *mut c_void,
finalize_cb: napi_finalize,
finalize_hint: *mut c_void,
result: *mut napi_value,
) -> napi_status;
fn napi_get_value_external(
env: napi_env,
value: napi_value,
result: *mut *mut c_void,
) -> napi_status;
fn napi_create_reference(
env: napi_env,
value: napi_value,
initial_refcount: u32,
result: *mut napi_ref,
) -> napi_status;
fn napi_delete_reference(env: napi_env, ref_: napi_ref) -> napi_status;
fn napi_reference_ref(env: napi_env, ref_: napi_ref, result: *mut u32) -> napi_status;
fn napi_reference_unref(env: napi_env, ref_: napi_ref, result: *mut u32) -> napi_status;
fn napi_get_reference_value(
env: napi_env,
ref_: napi_ref,
result: *mut napi_value,
) -> napi_status;
fn napi_open_handle_scope(env: napi_env, result: *mut napi_handle_scope) -> napi_status;
fn napi_close_handle_scope(env: napi_env, scope: napi_handle_scope) -> napi_status;
fn napi_open_escapable_handle_scope(
env: napi_env,
result: *mut napi_escapable_handle_scope,
) -> napi_status;
fn napi_close_escapable_handle_scope(
env: napi_env,
scope: napi_escapable_handle_scope,
) -> napi_status;
fn napi_escape_handle(
env: napi_env,
scope: napi_escapable_handle_scope,
escapee: napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_throw(env: napi_env, error: napi_value) -> napi_status;
fn napi_throw_error(env: napi_env, code: *const c_char, msg: *const c_char) -> napi_status;
fn napi_throw_type_error(
env: napi_env,
code: *const c_char,
msg: *const c_char,
) -> napi_status;
fn napi_throw_range_error(
env: napi_env,
code: *const c_char,
msg: *const c_char,
) -> napi_status;
fn napi_is_error(env: napi_env, value: napi_value, result: *mut bool) -> napi_status;
fn napi_is_exception_pending(env: napi_env, result: *mut bool) -> napi_status;
fn napi_get_and_clear_last_exception(env: napi_env, result: *mut napi_value) -> napi_status;
fn napi_is_arraybuffer(env: napi_env, value: napi_value, result: *mut bool) -> napi_status;
fn napi_create_arraybuffer(
env: napi_env,
byte_length: usize,
data: *mut *mut c_void,
result: *mut napi_value,
) -> napi_status;
fn napi_create_external_arraybuffer(
env: napi_env,
external_data: *mut c_void,
byte_length: usize,
finalize_cb: napi_finalize,
finalize_hint: *mut c_void,
result: *mut napi_value,
) -> napi_status;
fn napi_get_arraybuffer_info(
env: napi_env,
arraybuffer: napi_value,
data: *mut *mut c_void,
byte_length: *mut usize,
) -> napi_status;
fn napi_is_typedarray(env: napi_env, value: napi_value, result: *mut bool) -> napi_status;
fn napi_create_typedarray(
env: napi_env,
type_: napi_typedarray_type,
length: usize,
arraybuffer: napi_value,
byte_offset: usize,
result: *mut napi_value,
) -> napi_status;
fn napi_get_typedarray_info(
env: napi_env,
typedarray: napi_value,
type_: *mut napi_typedarray_type,
length: *mut usize,
data: *mut *mut c_void,
arraybuffer: *mut napi_value,
byte_offset: *mut usize,
) -> napi_status;
fn napi_create_dataview(
env: napi_env,
length: usize,
arraybuffer: napi_value,
byte_offset: usize,
result: *mut napi_value,
) -> napi_status;
fn napi_is_dataview(env: napi_env, value: napi_value, result: *mut bool) -> napi_status;
fn napi_get_dataview_info(
env: napi_env,
dataview: napi_value,
bytelength: *mut usize,
data: *mut *mut c_void,
arraybuffer: *mut napi_value,
byte_offset: *mut usize,
) -> napi_status;
fn napi_get_version(env: napi_env, result: *mut u32) -> napi_status;
fn napi_create_promise(
env: napi_env,
deferred: *mut napi_deferred,
promise: *mut napi_value,
) -> napi_status;
fn napi_resolve_deferred(
env: napi_env,
deferred: napi_deferred,
resolution: napi_value,
) -> napi_status;
fn napi_reject_deferred(
env: napi_env,
deferred: napi_deferred,
rejection: napi_value,
) -> napi_status;
fn napi_is_promise(env: napi_env, value: napi_value, is_promise: *mut bool) -> napi_status;
fn napi_run_script(env: napi_env, script: napi_value, result: *mut napi_value)
-> napi_status;
fn napi_adjust_external_memory(
env: napi_env,
change_in_bytes: i64,
adjusted_value: *mut i64,
) -> napi_status;
fn napi_module_register(mod_: *mut napi_module);
fn napi_fatal_error(
location: *const c_char,
location_len: usize,
message: *const c_char,
message_len: usize,
);
fn napi_async_init(
env: napi_env,
async_resource: napi_value,
async_resource_name: napi_value,
result: *mut napi_async_context,
) -> napi_status;
fn napi_async_destroy(env: napi_env, async_context: napi_async_context) -> napi_status;
fn napi_make_callback(
env: napi_env,
async_context: napi_async_context,
recv: napi_value,
func: napi_value,
argc: usize,
argv: *const napi_value,
result: *mut napi_value,
) -> napi_status;
fn napi_create_buffer(
env: napi_env,
length: usize,
data: *mut *mut c_void,
result: *mut napi_value,
) -> napi_status;
fn napi_create_external_buffer(
env: napi_env,
length: usize,
data: *mut c_void,
finalize_cb: napi_finalize,
finalize_hint: *mut c_void,
result: *mut napi_value,
) -> napi_status;
fn napi_create_buffer_copy(
env: napi_env,
length: usize,
data: *const c_void,
result_data: *mut *mut c_void,
result: *mut napi_value,
) -> napi_status;
fn napi_is_buffer(env: napi_env, value: napi_value, result: *mut bool) -> napi_status;
fn napi_get_buffer_info(
env: napi_env,
value: napi_value,
data: *mut *mut c_void,
length: *mut usize,
) -> napi_status;
fn napi_create_async_work(
env: napi_env,
async_resource: napi_value,
async_resource_name: napi_value,
execute: napi_async_execute_callback,
complete: napi_async_complete_callback,
data: *mut c_void,
result: *mut napi_async_work,
) -> napi_status;
fn napi_delete_async_work(env: napi_env, work: napi_async_work) -> napi_status;
fn napi_queue_async_work(env: napi_env, work: napi_async_work) -> napi_status;
fn napi_cancel_async_work(env: napi_env, work: napi_async_work) -> napi_status;
fn napi_get_node_version(
env: napi_env,
version: *mut *const napi_node_version,
) -> napi_status;
}
);
}
#[cfg(feature = "napi2")]
mod napi2 {
use super::super::types::*;
generate!(
extern "C" {
fn napi_get_uv_event_loop(env: napi_env, loop_: *mut *mut uv_loop_s) -> napi_status;
}
);
}
#[cfg(feature = "napi3")]
mod napi3 {
use std::os::raw::c_void;
use super::super::types::*;
generate!(
extern "C" {
fn napi_fatal_exception(env: napi_env, err: napi_value) -> napi_status;
fn napi_add_env_cleanup_hook(
env: napi_env,
fun: Option<unsafe extern "C" fn(arg: *mut c_void)>,
arg: *mut c_void,
) -> napi_status;
fn napi_remove_env_cleanup_hook(
env: napi_env,
fun: Option<unsafe extern "C" fn(arg: *mut c_void)>,
arg: *mut c_void,
) -> napi_status;
fn napi_open_callback_scope(
env: napi_env,
resource_object: napi_value,
context: napi_async_context,
result: *mut napi_callback_scope,
) -> napi_status;
fn napi_close_callback_scope(env: napi_env, scope: napi_callback_scope) -> napi_status;
}
);
}
#[cfg(feature = "napi4")]
mod napi4 {
use super::super::types::*;
use std::os::raw::c_void;
generate!(
extern "C" {
fn napi_create_threadsafe_function(
env: napi_env,
func: napi_value,
async_resource: napi_value,
async_resource_name: napi_value,
max_queue_size: usize,
initial_thread_count: usize,
thread_finalize_data: *mut c_void,
thread_finalize_cb: napi_finalize,
context: *mut c_void,
call_js_cb: napi_threadsafe_function_call_js,
result: *mut napi_threadsafe_function,
) -> napi_status;
fn napi_get_threadsafe_function_context(
func: napi_threadsafe_function,
result: *mut *mut c_void,
) -> napi_status;
fn napi_call_threadsafe_function(
func: napi_threadsafe_function,
data: *mut c_void,
is_blocking: napi_threadsafe_function_call_mode,
) -> napi_status;
fn napi_acquire_threadsafe_function(func: napi_threadsafe_function) -> napi_status;
fn napi_release_threadsafe_function(
func: napi_threadsafe_function,
mode: napi_threadsafe_function_release_mode,
) -> napi_status;
fn napi_unref_threadsafe_function(
env: napi_env,
func: napi_threadsafe_function,
) -> napi_status;
fn napi_ref_threadsafe_function(env: napi_env, func: napi_threadsafe_function)
-> napi_status;
}
);
}
#[cfg(feature = "napi5")]
mod napi5 {
use super::super::types::*;
use std::ffi::c_void;
generate!(
extern "C" {
fn napi_create_date(env: napi_env, time: f64, result: *mut napi_value) -> napi_status;
fn napi_is_date(env: napi_env, value: napi_value, is_date: *mut bool) -> napi_status;
fn napi_get_date_value(env: napi_env, value: napi_value, result: *mut f64) -> napi_status;
fn napi_add_finalizer(
env: napi_env,
js_object: napi_value,
native_object: *mut c_void,
finalize_cb: napi_finalize,
finalize_hint: *mut c_void,
result: *mut napi_ref,
) -> napi_status;
}
);
}
#[cfg(feature = "napi6")]
mod napi6 {
use super::super::types::*;
use std::os::raw::{c_int, c_void};
generate!(
extern "C" {
fn napi_create_bigint_int64(
env: napi_env,
value: i64,
result: *mut napi_value,
) -> napi_status;
fn napi_create_bigint_uint64(
env: napi_env,
value: u64,
result: *mut napi_value,
) -> napi_status;
fn napi_create_bigint_words(
env: napi_env,
sign_bit: c_int,
word_count: usize,
words: *const u64,
result: *mut napi_value,
) -> napi_status;
fn napi_get_value_bigint_int64(
env: napi_env,
value: napi_value,
result: *mut i64,
lossless: *mut bool,
) -> napi_status;
fn napi_get_value_bigint_uint64(
env: napi_env,
value: napi_value,
result: *mut u64,
lossless: *mut bool,
) -> napi_status;
fn napi_get_value_bigint_words(
env: napi_env,
value: napi_value,
sign_bit: *mut c_int,
word_count: *mut usize,
words: *mut u64,
) -> napi_status;
fn napi_get_all_property_names(
env: napi_env,
object: napi_value,
key_mode: napi_key_collection_mode,
key_filter: napi_key_filter,
key_conversion: napi_key_conversion,
result: *mut napi_value,
) -> napi_status;
fn napi_set_instance_data(
env: napi_env,
data: *mut c_void,
finalize_cb: napi_finalize,
finalize_hint: *mut c_void,
) -> napi_status;
fn napi_get_instance_data(env: napi_env, data: *mut *mut c_void) -> napi_status;
}
);
}
#[cfg(feature = "napi7")]
mod napi7 {
use super::super::types::*;
generate!(
extern "C" {
fn napi_detach_arraybuffer(env: napi_env, arraybuffer: napi_value) -> napi_status;
fn napi_is_detached_arraybuffer(
env: napi_env,
value: napi_value,
result: *mut bool,
) -> napi_status;
}
);
}
#[cfg(feature = "napi8")]
mod napi8 {
use std::os::raw::c_void;
use super::super::types::*;
generate!(
extern "C" {
fn napi_add_async_cleanup_hook(
env: napi_env,
hook: napi_async_cleanup_hook,
arg: *mut c_void,
remove_handle: *mut napi_async_cleanup_hook_handle,
) -> napi_status;
fn napi_remove_async_cleanup_hook(
remove_handle: napi_async_cleanup_hook_handle,
) -> napi_status;
fn napi_object_freeze(env: napi_env, object: napi_value) -> napi_status;
fn napi_object_seal(env: napi_env, object: napi_value) -> napi_status;
}
);
}
#[cfg(feature = "experimental")]
mod experimental {
use std::os::raw::c_char;
use super::super::types::*;
generate!(
extern "C" {
fn node_api_get_module_file_name(env: napi_env, result: *mut *const c_char) -> napi_status;
fn node_api_create_syntax_error(
env: napi_env,
code: napi_value,
msg: napi_value,
result: *mut napi_value,
) -> napi_status;
fn node_api_throw_syntax_error(
env: napi_env,
code: *const c_char,
msg: *const c_char,
) -> napi_status;
}
);
}
#[cfg(feature = "experimental")]
pub use experimental::*;
pub use napi1::*;
#[cfg(feature = "napi2")]
pub use napi2::*;
#[cfg(feature = "napi3")]
pub use napi3::*;
#[cfg(feature = "napi4")]
pub use napi4::*;
#[cfg(feature = "napi5")]
pub use napi5::*;
#[cfg(feature = "napi6")]
pub use napi6::*;
#[cfg(feature = "napi7")]
pub use napi7::*;
#[cfg(feature = "napi8")]
pub use napi8::*;
#[cfg(windows)]
pub(super) unsafe fn load() -> Result<(), libloading::Error> {
#[cfg(not(windows))]
let host = libloading::os::unix::Library::this().into();
#[cfg(windows)]
let host = libloading::os::windows::Library::this()?.into();
napi1::load(&host)?;
#[cfg(feature = "napi2")]
napi2::load(&host)?;
#[cfg(feature = "napi3")]
napi3::load(&host)?;
#[cfg(feature = "napi4")]
napi4::load(&host)?;
#[cfg(feature = "napi5")]
napi5::load(&host)?;
#[cfg(feature = "napi6")]
napi6::load(&host)?;
#[cfg(feature = "napi7")]
napi7::load(&host)?;
#[cfg(feature = "napi8")]
napi8::load(&host)?;
#[cfg(feature = "experimental")]
experimental::load(&host)?;
Ok(())
}

File diff suppressed because it is too large Load diff

295
crates/sys/src/types.rs Normal file
View file

@ -0,0 +1,295 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
use std::os::raw::{c_char, c_int, c_uint, c_void};
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_env__ {
_unused: [u8; 0],
}
/// Env ptr
pub type napi_env = *mut napi_env__;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_value__ {
_unused: [u8; 0],
}
/// JsValue ptr
pub type napi_value = *mut napi_value__;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_ref__ {
_unused: [u8; 0],
}
pub type napi_ref = *mut napi_ref__;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_handle_scope__ {
_unused: [u8; 0],
}
pub type napi_handle_scope = *mut napi_handle_scope__;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_escapable_handle_scope__ {
_unused: [u8; 0],
}
pub type napi_escapable_handle_scope = *mut napi_escapable_handle_scope__;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_callback_info__ {
_unused: [u8; 0],
}
pub type napi_callback_info = *mut napi_callback_info__;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_deferred__ {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct uv_loop_s {
_unused: [u8; 0],
}
pub type napi_deferred = *mut napi_deferred__;
pub type napi_property_attributes = i32;
pub mod PropertyAttributes {
use super::napi_property_attributes;
pub const default: napi_property_attributes = 0;
pub const writable: napi_property_attributes = 1 << 0;
pub const enumerable: napi_property_attributes = 1 << 1;
pub const configurable: napi_property_attributes = 1 << 2;
// Used with napi_define_class to distinguish static properties
// from instance properties. Ignored by napi_define_properties.
pub const static_: napi_property_attributes = 1 << 10;
}
pub type napi_valuetype = i32;
pub mod ValueType {
pub const napi_undefined: i32 = 0;
pub const napi_null: i32 = 1;
pub const napi_boolean: i32 = 2;
pub const napi_number: i32 = 3;
pub const napi_string: i32 = 4;
pub const napi_symbol: i32 = 5;
pub const napi_object: i32 = 6;
pub const napi_function: i32 = 7;
pub const napi_external: i32 = 8;
#[cfg(feature = "napi6")]
pub const napi_bigint: i32 = 9;
}
pub type napi_typedarray_type = i32;
pub mod TypedarrayType {
pub const int8_array: i32 = 0;
pub const uint8_array: i32 = 1;
pub const uint8_clamped_array: i32 = 2;
pub const int16_array: i32 = 3;
pub const uint16_array: i32 = 4;
pub const int32_array: i32 = 5;
pub const uint32_array: i32 = 6;
pub const float32_array: i32 = 7;
pub const float64_array: i32 = 8;
#[cfg(feature = "napi6")]
pub const bigint64_array: i32 = 9;
#[cfg(feature = "napi6")]
pub const biguint64_array: i32 = 10;
}
pub type napi_status = i32;
pub mod Status {
pub const napi_ok: i32 = 0;
pub const napi_invalid_arg: i32 = 1;
pub const napi_object_expected: i32 = 2;
pub const napi_string_expected: i32 = 3;
pub const napi_name_expected: i32 = 4;
pub const napi_function_expected: i32 = 5;
pub const napi_number_expected: i32 = 6;
pub const napi_boolean_expected: i32 = 7;
pub const napi_array_expected: i32 = 8;
pub const napi_generic_failure: i32 = 9;
pub const napi_pending_exception: i32 = 10;
pub const napi_cancelled: i32 = 11;
pub const napi_escape_called_twice: i32 = 12;
pub const napi_handle_scope_mismatch: i32 = 13;
pub const napi_callback_scope_mismatch: i32 = 14;
pub const napi_queue_full: i32 = 15;
pub const napi_closing: i32 = 16;
pub const napi_bigint_expected: i32 = 17;
pub const napi_date_expected: i32 = 18;
pub const napi_arraybuffer_expected: i32 = 19;
pub const napi_detachable_arraybuffer_expected: i32 = 20;
pub const napi_would_deadlock: i32 = 21; // unused
}
pub type napi_callback =
Option<unsafe extern "C" fn(env: napi_env, info: napi_callback_info) -> napi_value>;
pub type napi_finalize = Option<
unsafe extern "C" fn(env: napi_env, finalize_data: *mut c_void, finalize_hint: *mut c_void),
>;
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct napi_property_descriptor {
pub utf8name: *const c_char,
pub name: napi_value,
pub method: napi_callback,
pub getter: napi_callback,
pub setter: napi_callback,
pub value: napi_value,
pub attributes: napi_property_attributes,
pub data: *mut c_void,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_extended_error_info {
pub error_message: *const c_char,
pub engine_reserved: *mut c_void,
pub engine_error_code: u32,
pub error_code: napi_status,
}
#[cfg(feature = "napi6")]
pub type napi_key_collection_mode = i32;
#[cfg(feature = "napi6")]
pub mod KeyCollectionMode {
pub use super::napi_key_collection_mode;
pub const include_prototypes: napi_key_collection_mode = 0;
pub const own_only: napi_key_collection_mode = 1;
}
#[cfg(feature = "napi6")]
pub type napi_key_filter = i32;
#[cfg(feature = "napi6")]
pub mod KeyFilter {
use super::napi_key_filter;
pub const all_properties: napi_key_filter = 0;
pub const writable: napi_key_filter = 1;
pub const enumerable: napi_key_filter = 1 << 1;
pub const configurable: napi_key_filter = 1 << 2;
pub const skip_strings: napi_key_filter = 1 << 3;
pub const skip_symbols: napi_key_filter = 1 << 4;
}
#[cfg(feature = "napi6")]
pub type napi_key_conversion = i32;
#[cfg(feature = "napi6")]
pub mod KeyConversion {
use super::napi_key_conversion;
pub const keep_numbers: napi_key_conversion = 0;
pub const numbers_to_strings: napi_key_conversion = 1;
}
#[cfg(feature = "napi8")]
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct napi_async_cleanup_hook_handle__ {
_unused: [u8; 0],
}
#[cfg(feature = "napi8")]
pub type napi_async_cleanup_hook_handle = *mut napi_async_cleanup_hook_handle__;
#[cfg(feature = "napi8")]
pub type napi_async_cleanup_hook =
Option<unsafe extern "C" fn(handle: napi_async_cleanup_hook_handle, data: *mut c_void)>;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_callback_scope__ {
_unused: [u8; 0],
}
pub type napi_callback_scope = *mut napi_callback_scope__;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_async_context__ {
_unused: [u8; 0],
}
pub type napi_async_context = *mut napi_async_context__;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_async_work__ {
_unused: [u8; 0],
}
pub type napi_async_work = *mut napi_async_work__;
#[cfg(feature = "napi4")]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_threadsafe_function__ {
_unused: [u8; 0],
}
#[cfg(feature = "napi4")]
pub type napi_threadsafe_function = *mut napi_threadsafe_function__;
#[cfg(feature = "napi4")]
pub type napi_threadsafe_function_release_mode = i32;
#[cfg(feature = "napi4")]
pub mod ThreadsafeFunctionReleaseMode {
use super::napi_threadsafe_function_release_mode;
pub const release: napi_threadsafe_function_release_mode = 0;
pub const abort: napi_threadsafe_function_release_mode = 1;
}
#[cfg(feature = "napi4")]
pub type napi_threadsafe_function_call_mode = i32;
#[cfg(feature = "napi4")]
pub mod ThreadsafeFunctionCallMode {
use super::napi_threadsafe_function_call_mode;
pub const nonblocking: napi_threadsafe_function_call_mode = 0;
pub const blocking: napi_threadsafe_function_call_mode = 1;
}
pub type napi_async_execute_callback =
Option<unsafe extern "C" fn(env: napi_env, data: *mut c_void)>;
pub type napi_async_complete_callback =
Option<unsafe extern "C" fn(env: napi_env, status: napi_status, data: *mut c_void)>;
#[cfg(feature = "napi4")]
pub type napi_threadsafe_function_call_js = Option<
unsafe extern "C" fn(
env: napi_env,
js_callback: napi_value,
context: *mut c_void,
data: *mut c_void,
),
>;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_node_version {
pub major: u32,
pub minor: u32,
pub patch: u32,
pub release: *const c_char,
}
pub type napi_addon_register_func =
Option<unsafe extern "C" fn(env: napi_env, exports: napi_value) -> napi_value>;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct napi_module {
pub nm_version: c_int,
pub nm_flags: c_uint,
pub nm_filename: *const c_char,
pub nm_register_func: napi_addon_register_func,
pub nm_modname: *const c_char,
pub nm_priv: *mut c_void,
pub reserved: [*mut c_void; 4usize],
}