refactor(napi-sys): remove bindgen
This commit is contained in:
parent
f376f3615c
commit
fc0ec0b378
39 changed files with 1428 additions and 597 deletions
|
@ -7,7 +7,7 @@ task:
|
|||
DEBUG: 'napi:*'
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y -f curl node yarn npm libnghttp2 llvm
|
||||
- pkg install -y -f curl node yarn npm libnghttp2
|
||||
- curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||
- sh rustup.sh -y --profile minimal --default-toolchain stable
|
||||
- . $HOME/.cargo/env
|
||||
|
|
3
.github/workflows/bench.yaml
vendored
3
.github/workflows/bench.yaml
vendored
|
@ -18,9 +18,10 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2-beta
|
||||
with:
|
||||
node-version: 14
|
||||
check-latest: true
|
||||
|
||||
- name: Install
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
|
5
.github/workflows/lint.yaml
vendored
5
.github/workflows/lint.yaml
vendored
|
@ -14,9 +14,10 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2-beta
|
||||
with:
|
||||
node-version: 12
|
||||
node-version: 14
|
||||
check-latest: true
|
||||
|
||||
- name: Install
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
|
3
.github/workflows/linux-aarch64.yaml
vendored
3
.github/workflows/linux-aarch64.yaml
vendored
|
@ -21,9 +21,10 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2-beta
|
||||
with:
|
||||
node-version: 14
|
||||
check-latest: true
|
||||
|
||||
- name: Install
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
|
4
.github/workflows/linux-musl.yaml
vendored
4
.github/workflows/linux-musl.yaml
vendored
|
@ -42,10 +42,6 @@ jobs:
|
|||
run: |
|
||||
docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder cargo check -vvv
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder cargo test -p napi-sys --lib -- --nocapture
|
||||
|
||||
- name: Unit test
|
||||
run: |
|
||||
docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder sh -c "yarn build:test && yarn test"
|
||||
|
|
9
.github/workflows/napi3.yaml
vendored
9
.github/workflows/napi3.yaml
vendored
|
@ -69,16 +69,9 @@ jobs:
|
|||
command: check
|
||||
args: --all --bins --examples --tests -vvv
|
||||
|
||||
- name: Tests
|
||||
uses: actions-rs/cargo@v1
|
||||
timeout-minutes: 5
|
||||
with:
|
||||
command: test
|
||||
args: -p napi-sys --lib -- --nocapture
|
||||
|
||||
- name: Unit tests
|
||||
run: |
|
||||
yarn --cwd ./test_module --ignore-engines build
|
||||
yarn --cwd ./test_module --ignore-engines build-napi3
|
||||
yarn --ignore-engines test
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
|
|
22
.github/workflows/test.yaml
vendored
22
.github/workflows/test.yaml
vendored
|
@ -13,7 +13,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: ['10', '12', '14']
|
||||
node: ['10', '12', '14', '15']
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
name: stable - ${{ matrix.os }} - node@${{ matrix.node }}
|
||||
|
@ -23,19 +23,10 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2-beta
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
- name: Install llvm
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: choco install -y llvm
|
||||
|
||||
- name: Set llvm path
|
||||
if: matrix.os == 'windows-latest'
|
||||
uses: allenevans/set-env@v1.1.0
|
||||
with:
|
||||
LIBCLANG_PATH: 'C:\Program Files\LLVM\bin'
|
||||
check-latest: true
|
||||
|
||||
- name: Install
|
||||
uses: actions-rs/toolchain@v1
|
||||
|
@ -81,13 +72,6 @@ jobs:
|
|||
command: check
|
||||
args: --all --bins --examples --tests -vvv
|
||||
|
||||
- name: Tests
|
||||
uses: actions-rs/cargo@v1
|
||||
timeout-minutes: 5
|
||||
with:
|
||||
command: test
|
||||
args: -p napi-sys --lib -- --nocapture
|
||||
|
||||
- name: Unit tests
|
||||
run: |
|
||||
yarn build:test
|
||||
|
|
42
.github/workflows/windows-i686.yml
vendored
42
.github/workflows/windows-i686.yml
vendored
|
@ -17,17 +17,27 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14
|
||||
run: choco install nodejs-lts --x86 -y --force
|
||||
|
||||
- name: Install llvm
|
||||
run: choco install -y llvm
|
||||
|
||||
- name: Set llvm path
|
||||
run: echo "LIBCLANG_PATH=C:\\Program Files\\LLVM\\bin" >> $GITHUB_ENV
|
||||
- name: Set 32bit NodeJS path
|
||||
run: |
|
||||
echo "C:\\Program Files (x86)\\nodejs" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
||||
- name: Cache NPM dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: node_modules
|
||||
key: npm-cache-windows-i686-node@lts-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
npm-cache-
|
||||
|
||||
- name: 'Install dependencies'
|
||||
run: yarn install --frozen-lockfile --registry https://registry.npmjs.org
|
||||
|
||||
- name: 'Build TypeScript'
|
||||
run: yarn build
|
||||
|
||||
- name: Install
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
|
@ -47,13 +57,13 @@ jobs:
|
|||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: stable-${{ matrix.os }}-node@${{ matrix.node }}-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: stable-windows-i686-node@lts-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo index
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: stable-${{ matrix.os }}gnu-node@${{ matrix.node }}-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: stable-windows-i686-node@lts-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Check build
|
||||
uses: actions-rs/cargo@v1
|
||||
|
@ -61,12 +71,12 @@ jobs:
|
|||
command: check
|
||||
args: --all --bins --examples --tests --target i686-pc-windows-msvc -vvv
|
||||
|
||||
- name: Tests
|
||||
uses: actions-rs/cargo@v1
|
||||
timeout-minutes: 5
|
||||
with:
|
||||
command: test
|
||||
args: -p napi-sys --lib --target i686-pc-windows-msvc -- --nocapture
|
||||
- name: Build Tests
|
||||
run: |
|
||||
yarn --cwd ./test_module build-i686
|
||||
yarn test
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
|
|
|
@ -28,9 +28,9 @@ A minimal library for building compiled `NodeJS` add-ons in `Rust`.
|
|||
|
||||
## NodeJS
|
||||
|
||||
| Node10 | Node 12 | Node14 |
|
||||
| ------ | ------- | ------ |
|
||||
| ✓ | ✓ | ✓ |
|
||||
| Node10 | Node 12 | Node14 | Node15 |
|
||||
| ------ | ------- | ------ | ------ |
|
||||
| ✓ | ✓ | ✓ | ✓ |
|
||||
|
||||
This library depends on N-API and requires `Node@8.9` or later.
|
||||
|
||||
|
|
|
@ -8,14 +8,8 @@ version = "0.1.0"
|
|||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3"
|
||||
napi = {path = "../napi", features = ["libuv", "tokio_rt", "serde-json", "latin1"]}
|
||||
napi = {path = "../napi"}
|
||||
napi-derive = {path = "../napi-derive"}
|
||||
serde = "1"
|
||||
serde_bytes = "0.11"
|
||||
serde_derive = "1"
|
||||
serde_json = "1"
|
||||
tokio = {version = "0.2", features = ["default", "fs"]}
|
||||
|
||||
[build-dependencies]
|
||||
napi-build = {path = "../build"}
|
||||
|
|
|
@ -1,40 +1,11 @@
|
|||
cfg_if::cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
mod windows;
|
||||
pub use windows::setup;
|
||||
} else if #[cfg(target_os = "macos")] {
|
||||
mod macos;
|
||||
pub use macos::setup;
|
||||
} else {
|
||||
pub fn setup() {
|
||||
setup_napi_feature();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
pub fn setup_napi_feature() {
|
||||
let napi_version = String::from_utf8(
|
||||
Command::new("node")
|
||||
.args(&["-e", "console.log(process.versions.napi)"])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout,
|
||||
)
|
||||
.expect("Get NAPI version failed");
|
||||
|
||||
let napi_version_number = napi_version.trim().parse::<u32>().unwrap();
|
||||
|
||||
if napi_version_number < 2 {
|
||||
panic!("current napi version is too low");
|
||||
}
|
||||
|
||||
if napi_version_number == 2 {
|
||||
println!("cargo:rustc-cfg=napi{}", napi_version_number);
|
||||
if #[cfg(windows)] {
|
||||
mod windows;
|
||||
pub use windows::setup;
|
||||
} else if #[cfg(target_os = "macos")] {
|
||||
mod macos;
|
||||
pub use macos::setup;
|
||||
} else {
|
||||
for version in 2..(napi_version_number + 1) {
|
||||
println!("cargo:rustc-cfg=napi{}", version);
|
||||
}
|
||||
pub fn setup() { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
use crate::*;
|
||||
|
||||
pub fn setup() {
|
||||
println!("cargo:rustc-cdylib-link-arg=-Wl");
|
||||
println!("cargo:rustc-cdylib-link-arg=-undefined");
|
||||
println!("cargo:rustc-cdylib-link-arg=dynamic_lookup");
|
||||
setup_napi_feature();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::*;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::fs::{metadata, write};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
fn get_node_version() -> std::io::Result<String> {
|
||||
let output = Command::new("node").arg("-v").output()?;
|
||||
|
@ -51,16 +51,17 @@ pub fn setup() {
|
|||
// 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 = std::env::var("CARGO_CFG_TARGET_ARCH")
|
||||
.map(|arch| match arch.as_str() {
|
||||
"x86" => "x86", // TODO: x86 appears to also be called ia32 in npm_config_arch sometimes. What is the right value?
|
||||
"x86" => "x86",
|
||||
"x86_64" => "x64",
|
||||
"mips" => "mips",
|
||||
"powerpc" => "ppc",
|
||||
"powerpc64" => "ppc64",
|
||||
"arm" => "arm",
|
||||
// https://github.com/nodejs/node/issues/25998
|
||||
// actually not supported for now
|
||||
// because we can not get `node.lib` file for `aarch64` device
|
||||
"aarch64" => "arm64",
|
||||
arch => panic!("Unknown Architecture: {}", arch),
|
||||
arch => panic!("Unsupported CPU Architecture: {}", arch),
|
||||
})
|
||||
.expect("Failed to determine target arch");
|
||||
|
||||
|
@ -106,6 +107,4 @@ pub fn setup() {
|
|||
);
|
||||
println!("cargo:rustc-cdylib-link-arg=delayimp.lib");
|
||||
println!("cargo:rustc-cdylib-link-arg=/DELAYLOAD:node.exe");
|
||||
|
||||
setup_napi_feature();
|
||||
}
|
||||
|
|
|
@ -10,8 +10,15 @@ repository = "https://github.com/napi-rs/napi-rs"
|
|||
version = "0.5.1"
|
||||
|
||||
[features]
|
||||
default = ["napi3"] # for most NodeJS users
|
||||
latin1 = ["encoding_rs"]
|
||||
libuv = ["futures"]
|
||||
napi1 = []
|
||||
napi2 = ["napi1"]
|
||||
napi3 = ["napi2", "napi-sys/napi3"]
|
||||
napi4 = ["napi3", "napi-sys/napi4"]
|
||||
napi5 = ["napi4", "napi-sys/napi5"]
|
||||
napi6 = ["napi5", "napi-sys/napi6"]
|
||||
napi7 = ["napi6", "napi-sys/napi7"]
|
||||
serde-json = ["serde", "serde_json"]
|
||||
tokio_rt = ["futures", "tokio", "once_cell"]
|
||||
|
||||
|
@ -51,4 +58,3 @@ napi-build = {version = "0.2", path = "../build"}
|
|||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustc-args = ["--cfg", "napidocsrs"]
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
fn main() {
|
||||
napi_build::setup_napi_feature();
|
||||
}
|
|
@ -5,30 +5,29 @@ use std::mem;
|
|||
use std::os::raw::{c_char, c_void};
|
||||
use std::ptr;
|
||||
|
||||
use super::cleanup_env::{CleanupEnvHook, CleanupEnvHookData};
|
||||
use crate::async_work::{self, AsyncWorkPromise};
|
||||
use crate::error::check_status;
|
||||
use crate::js_values::*;
|
||||
use crate::task::Task;
|
||||
use crate::{sys, Error, NodeVersion, Result, Status};
|
||||
|
||||
#[cfg(feature = "napi3")]
|
||||
use super::cleanup_env::{CleanupEnvHook, CleanupEnvHookData};
|
||||
#[cfg(all(feature = "serde-json"))]
|
||||
use crate::js_values::{De, Ser};
|
||||
#[cfg(all(any(feature = "libuv", feature = "tokio_rt"), napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
use crate::promise;
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
use crate::threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction};
|
||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
use crate::tokio_rt::{get_tokio_sender, Message};
|
||||
#[cfg(all(feature = "libuv", napi4))]
|
||||
use crate::uv;
|
||||
#[cfg(all(feature = "serde-json"))]
|
||||
use serde::de::DeserializeOwned;
|
||||
#[cfg(all(feature = "serde-json"))]
|
||||
use serde::Serialize;
|
||||
#[cfg(all(feature = "libuv", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
use std::future::Future;
|
||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
use tokio::sync::mpsc::error::TrySendError;
|
||||
|
||||
pub type Callback = extern "C" fn(sys::napi_env, sys::napi_callback_info) -> sys::napi_value;
|
||||
|
@ -90,7 +89,7 @@ impl Env {
|
|||
Ok(JsNumber::from_raw_unchecked(self.0, raw_value))
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
/// [n_api_napi_create_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_int64)
|
||||
pub fn create_bigint_from_i64(&self, value: i64) -> Result<JsBigint> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
|
@ -98,14 +97,14 @@ impl Env {
|
|||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn create_bigint_from_u64(&self, value: u64) -> Result<JsBigint> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status(unsafe { sys::napi_create_bigint_uint64(self.0, value, &mut raw_value) })?;
|
||||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn create_bigint_from_i128(&self, value: i128) -> Result<JsBigint> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let sign_bit = if value > 0 { 0 } else { 1 };
|
||||
|
@ -116,7 +115,7 @@ impl Env {
|
|||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn create_bigint_from_u128(&self, value: u128) -> Result<JsBigint> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
let words = &value as *const u128 as *const u64;
|
||||
|
@ -124,7 +123,7 @@ impl Env {
|
|||
Ok(JsBigint::from_raw_unchecked(self.0, raw_value, 1))
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
/// [n_api_napi_create_bigint_words](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_words)
|
||||
/// The resulting BigInt will be negative when sign_bit is true.
|
||||
pub fn create_bigint_from_words(&self, sign_bit: bool, words: Vec<u64>) -> Result<JsBigint> {
|
||||
|
@ -549,14 +548,14 @@ impl Env {
|
|||
.map_err(|e| Error::new(Status::InvalidArg, format!("{}", e)))
|
||||
}
|
||||
|
||||
#[cfg(napi2)]
|
||||
#[cfg(feature = "napi2")]
|
||||
pub fn get_uv_event_loop(&self) -> Result<*mut sys::uv_loop_s> {
|
||||
let mut uv_loop: *mut sys::uv_loop_s = ptr::null_mut();
|
||||
check_status(unsafe { sys::napi_get_uv_event_loop(self.0, &mut uv_loop) })?;
|
||||
Ok(uv_loop)
|
||||
}
|
||||
|
||||
#[cfg(napi3)]
|
||||
#[cfg(feature = "napi3")]
|
||||
pub fn add_env_cleanup_hook<T, F>(
|
||||
&mut self,
|
||||
cleanup_data: T,
|
||||
|
@ -581,7 +580,7 @@ impl Env {
|
|||
Ok(CleanupEnvHook(hook_ref))
|
||||
}
|
||||
|
||||
#[cfg(napi3)]
|
||||
#[cfg(feature = "napi3")]
|
||||
pub fn remove_env_cleanup_hook<T>(&mut self, hook: CleanupEnvHook<T>) -> Result<()>
|
||||
where
|
||||
T: 'static,
|
||||
|
@ -591,7 +590,7 @@ impl Env {
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
pub fn create_threadsafe_function<
|
||||
T: Send,
|
||||
V: NapiValue,
|
||||
|
@ -605,31 +604,7 @@ impl Env {
|
|||
ThreadsafeFunction::create(self.0, func, max_queue_size, callback)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "libuv", napi4))]
|
||||
pub fn execute<
|
||||
T: 'static + Send,
|
||||
V: 'static + NapiValue,
|
||||
F: 'static + Future<Output = Result<T>>,
|
||||
R: 'static + Send + Sync + FnOnce(&mut Env, T) -> Result<V>,
|
||||
>(
|
||||
&self,
|
||||
deferred: F,
|
||||
resolver: R,
|
||||
) -> Result<JsObject> {
|
||||
let mut raw_promise = ptr::null_mut();
|
||||
let mut raw_deferred = ptr::null_mut();
|
||||
|
||||
check_status(unsafe { sys::napi_create_promise(self.0, &mut raw_deferred, &mut raw_promise) })?;
|
||||
|
||||
let event_loop = self.get_uv_event_loop()?;
|
||||
let future_promise = promise::FuturePromise::create(self.0, raw_deferred, Box::from(resolver))?;
|
||||
let future_to_execute = promise::resolve_from_future(future_promise.start()?, deferred);
|
||||
uv::execute(event_loop, Box::pin(future_to_execute))?;
|
||||
|
||||
Ok(JsObject::from_raw_unchecked(self.0, raw_promise))
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
pub fn execute_tokio_future<
|
||||
T: 'static + Send,
|
||||
V: 'static + NapiValue,
|
||||
|
@ -664,7 +639,7 @@ impl Env {
|
|||
Ok(JsObject::from_raw_unchecked(self.0, raw_promise))
|
||||
}
|
||||
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "napi5")]
|
||||
pub fn create_date(&self, time: f64) -> Result<JsDate> {
|
||||
let mut js_value = ptr::null_mut();
|
||||
check_status(unsafe { sys::napi_create_date(self.0, time, &mut js_value) })?;
|
||||
|
@ -738,6 +713,11 @@ impl Env {
|
|||
let version = unsafe { *result };
|
||||
version.try_into()
|
||||
}
|
||||
|
||||
/// get raw env ptr
|
||||
pub fn raw(&self) -> sys::napi_env {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn drop_buffer(env: sys::napi_env, finalize_data: *mut c_void, len: *mut c_void) {
|
||||
|
@ -759,6 +739,7 @@ unsafe extern "C" fn raw_finalize<T>(
|
|||
Box::from_raw(tagged_object);
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi3")]
|
||||
unsafe extern "C" fn cleanup_env<T: 'static>(hook_data: *mut c_void) {
|
||||
let cleanup_env_hook = Box::from_raw(hook_data as *mut CleanupEnvHookData<T>);
|
||||
(cleanup_env_hook.hook)(cleanup_env_hook.data);
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::ptr;
|
|||
|
||||
use super::{Value, ValueType};
|
||||
use crate::error::check_status;
|
||||
use crate::{sys, Error, JsUnknown, NapiValue, Ref, Result, Status};
|
||||
use crate::{sys, Error, JsUnknown, NapiValue, Ref, Result};
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
|
@ -44,6 +44,7 @@ pub struct JsDataViewValue {
|
|||
pub length: u64,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug)]
|
||||
pub enum TypedArrayType {
|
||||
Int8,
|
||||
|
@ -55,9 +56,9 @@ pub enum TypedArrayType {
|
|||
Uint32,
|
||||
Float32,
|
||||
Float64,
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
BigInt64,
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
BigUint64,
|
||||
}
|
||||
|
||||
|
@ -75,11 +76,10 @@ impl TryFrom<sys::napi_typedarray_type> for TypedArrayType {
|
|||
sys::napi_typedarray_type::napi_uint32_array => Ok(Self::Uint32),
|
||||
sys::napi_typedarray_type::napi_float32_array => Ok(Self::Float32),
|
||||
sys::napi_typedarray_type::napi_float64_array => Ok(Self::Float64),
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
sys::napi_typedarray_type::napi_bigint64_array => Ok(Self::BigInt64),
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
sys::napi_typedarray_type::napi_biguint64_array => Ok(Self::BigUint64),
|
||||
_ => Err(Error::from_status(Status::Unknown)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,21 +96,21 @@ impl From<TypedArrayType> for sys::napi_typedarray_type {
|
|||
TypedArrayType::Uint32 => sys::napi_typedarray_type::napi_uint32_array,
|
||||
TypedArrayType::Float32 => sys::napi_typedarray_type::napi_float32_array,
|
||||
TypedArrayType::Float64 => sys::napi_typedarray_type::napi_float64_array,
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
TypedArrayType::BigInt64 => sys::napi_typedarray_type::napi_bigint64_array,
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
TypedArrayType::BigUint64 => sys::napi_typedarray_type::napi_biguint64_array,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JsArrayBuffer {
|
||||
#[cfg(napi7)]
|
||||
#[cfg(feature = "napi7")]
|
||||
pub fn detach(self) -> Result<()> {
|
||||
check_status(unsafe { sys::napi_detach_arraybuffer(self.0.env, self.0.value) })
|
||||
}
|
||||
|
||||
#[cfg(napi7)]
|
||||
#[cfg(feature = "napi7")]
|
||||
pub fn is_detached(&self) -> Result<bool> {
|
||||
let mut is_detached = false;
|
||||
check_status(unsafe {
|
||||
|
|
|
@ -71,7 +71,7 @@ impl JsBigint {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "napi5")]
|
||||
pub fn is_date(&self) -> Result<bool> {
|
||||
let mut is_date = true;
|
||||
check_status(unsafe { sys::napi_is_date(self.raw.env, self.raw.value, &mut is_date) })?;
|
||||
|
|
|
@ -4,7 +4,7 @@ use serde::de::Visitor;
|
|||
use serde::de::{DeserializeSeed, EnumAccess, MapAccess, SeqAccess, Unexpected, VariantAccess};
|
||||
|
||||
use super::{type_of, NapiValue, Value, ValueType};
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
use crate::JsBigint;
|
||||
use crate::{
|
||||
Error, JsBoolean, JsBufferValue, JsNumber, JsObject, JsString, JsUnknown, Result, Status,
|
||||
|
@ -52,7 +52,7 @@ impl<'x, 'de, 'env> serde::de::Deserializer<'x> for &'de mut De<'env> {
|
|||
visitor.visit_map(&mut deserializer)
|
||||
}
|
||||
}
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
ValueType::Bigint => {
|
||||
let mut js_bigint = JsBigint::from_raw(self.0.env, self.0.value)?;
|
||||
let (signed, v, _loss) = js_bigint.get_u128()?;
|
||||
|
|
|
@ -11,11 +11,11 @@ mod de;
|
|||
mod ser;
|
||||
|
||||
mod arraybuffer;
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
mod bigint;
|
||||
mod boolean;
|
||||
mod buffer;
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "napi5")]
|
||||
mod date;
|
||||
mod either;
|
||||
mod escapable_handle_scope;
|
||||
|
@ -32,11 +32,11 @@ mod value_ref;
|
|||
mod value_type;
|
||||
|
||||
pub use arraybuffer::*;
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
pub use bigint::JsBigint;
|
||||
pub use boolean::JsBoolean;
|
||||
pub use buffer::*;
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "napi5")]
|
||||
pub use date::*;
|
||||
#[cfg(feature = "serde-json")]
|
||||
pub(crate) use de::De;
|
||||
|
@ -78,7 +78,7 @@ pub(crate) fn type_of(env: sys::napi_env, raw_value: sys::napi_value) -> Result<
|
|||
unsafe {
|
||||
let mut value_type = sys::napi_valuetype::napi_undefined;
|
||||
check_status(sys::napi_typeof(env, raw_value, &mut value_type))?;
|
||||
ValueType::try_from(value_type)
|
||||
Ok(ValueType::from(value_type))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ macro_rules! impl_js_value_methods {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "napi5")]
|
||||
pub fn is_date(&self) -> Result<bool> {
|
||||
let mut is_date = true;
|
||||
check_status(unsafe { sys::napi_is_date(self.0.env, self.0.value, &mut is_date) })?;
|
||||
|
@ -363,7 +363,7 @@ macro_rules! impl_object_methods {
|
|||
|
||||
/// https://nodejs.org/api/n-api.html#n_api_napi_get_all_property_names
|
||||
/// return `Array` of property names
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
pub fn get_all_property_names(
|
||||
&self,
|
||||
mode: KeyCollectionMode,
|
||||
|
@ -484,7 +484,7 @@ impl_js_value_methods!(JsNumber);
|
|||
impl_js_value_methods!(JsString);
|
||||
impl_js_value_methods!(JsObject);
|
||||
impl_js_value_methods!(JsGlobal);
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "napi5")]
|
||||
impl_js_value_methods!(JsDate);
|
||||
impl_js_value_methods!(JsFunction);
|
||||
impl_js_value_methods!(JsExternal);
|
||||
|
@ -511,7 +511,7 @@ impl_napi_value_trait!(JsNumber, Number);
|
|||
impl_napi_value_trait!(JsString, String);
|
||||
impl_napi_value_trait!(JsObject, Object);
|
||||
impl_napi_value_trait!(JsGlobal, Object);
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "napi5")]
|
||||
impl_napi_value_trait!(JsDate, Object);
|
||||
impl_napi_value_trait!(JsTimeout, Object);
|
||||
impl_napi_value_trait!(JsFunction, Function);
|
||||
|
@ -535,6 +535,7 @@ impl NapiValue for JsUnknown {
|
|||
})
|
||||
}
|
||||
|
||||
/// get raw js value ptr
|
||||
fn raw(&self) -> sys::napi_value {
|
||||
self.0.value
|
||||
}
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
use super::Value;
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
use crate::sys;
|
||||
use crate::{Error, Result, Status};
|
||||
#[cfg(feature = "napi6")]
|
||||
use crate::{Error, Result};
|
||||
#[cfg(feature = "napi6")]
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct JsObject(pub(crate) Value);
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
pub enum KeyCollectionMode {
|
||||
IncludePrototypes,
|
||||
OwnOnly,
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
impl TryFrom<sys::napi_key_collection_mode> for KeyCollectionMode {
|
||||
type Error = Error;
|
||||
|
||||
|
@ -22,12 +24,11 @@ impl TryFrom<sys::napi_key_collection_mode> for KeyCollectionMode {
|
|||
match value {
|
||||
sys::napi_key_collection_mode::napi_key_include_prototypes => Ok(Self::IncludePrototypes),
|
||||
sys::napi_key_collection_mode::napi_key_own_only => Ok(Self::OwnOnly),
|
||||
_ => Err(Error::from_status(Status::Unknown)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
impl From<KeyCollectionMode> for sys::napi_key_collection_mode {
|
||||
fn from(value: KeyCollectionMode) -> Self {
|
||||
match value {
|
||||
|
@ -39,7 +40,7 @@ impl From<KeyCollectionMode> for sys::napi_key_collection_mode {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
pub enum KeyFilter {
|
||||
AllProperties,
|
||||
Writable,
|
||||
|
@ -49,7 +50,7 @@ pub enum KeyFilter {
|
|||
SkipSymbols,
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
impl TryFrom<sys::napi_key_filter> for KeyFilter {
|
||||
type Error = Error;
|
||||
|
||||
|
@ -61,12 +62,11 @@ impl TryFrom<sys::napi_key_filter> for KeyFilter {
|
|||
sys::napi_key_filter::napi_key_configurable => Ok(Self::Configurable),
|
||||
sys::napi_key_filter::napi_key_skip_strings => Ok(Self::SkipStrings),
|
||||
sys::napi_key_filter::napi_key_skip_symbols => Ok(Self::SkipSymbols),
|
||||
_ => Err(Error::from_status(Status::Unknown)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
impl From<KeyFilter> for sys::napi_key_filter {
|
||||
fn from(value: KeyFilter) -> Self {
|
||||
match value {
|
||||
|
@ -80,13 +80,13 @@ impl From<KeyFilter> for sys::napi_key_filter {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
pub enum KeyConversion {
|
||||
KeepNumbers,
|
||||
NumbersToStrings,
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
impl TryFrom<sys::napi_key_conversion> for KeyConversion {
|
||||
type Error = Error;
|
||||
|
||||
|
@ -94,12 +94,11 @@ impl TryFrom<sys::napi_key_conversion> for KeyConversion {
|
|||
match value {
|
||||
sys::napi_key_conversion::napi_key_keep_numbers => Ok(Self::KeepNumbers),
|
||||
sys::napi_key_conversion::napi_key_numbers_to_strings => Ok(Self::NumbersToStrings),
|
||||
_ => Err(Error::from_status(Status::Unknown)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
impl From<KeyConversion> for sys::napi_key_conversion {
|
||||
fn from(value: KeyConversion) -> Self {
|
||||
match value {
|
||||
|
|
|
@ -13,11 +13,11 @@ pub struct Property<'env> {
|
|||
#[repr(u32)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum PropertyAttributes {
|
||||
Default = sys::napi_property_attributes::napi_default.0 as _,
|
||||
Writable = sys::napi_property_attributes::napi_writable.0 as _,
|
||||
Enumerable = sys::napi_property_attributes::napi_enumerable.0 as _,
|
||||
Configurable = sys::napi_property_attributes::napi_configurable.0 as _,
|
||||
Static = sys::napi_property_attributes::napi_static.0 as _,
|
||||
Default = sys::napi_property_attributes::napi_default as _,
|
||||
Writable = sys::napi_property_attributes::napi_writable as _,
|
||||
Enumerable = sys::napi_property_attributes::napi_enumerable as _,
|
||||
Configurable = sys::napi_property_attributes::napi_configurable as _,
|
||||
Static = sys::napi_property_attributes::napi_static as _,
|
||||
}
|
||||
|
||||
impl From<PropertyAttributes> for sys::napi_property_attributes {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::result::Result as StdResult;
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
use std::slice;
|
||||
|
||||
use serde::{ser, Serialize, Serializer};
|
||||
|
@ -92,13 +92,21 @@ impl<'env> Serializer for Ser<'env> {
|
|||
self.0.create_uint32(v).map(|js_number| js_number.0)
|
||||
}
|
||||
|
||||
#[cfg(all(any(napi2, napi3, napi4, napi5), not(napi6)))]
|
||||
#[cfg(all(
|
||||
any(
|
||||
feature = "napi2",
|
||||
feature = "napi3",
|
||||
feature = "napi4",
|
||||
feature = "napi5"
|
||||
),
|
||||
not(feature = "napi6")
|
||||
))]
|
||||
#[inline]
|
||||
fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
|
||||
self.0.create_int64(v as _).map(|js_number| js_number.0)
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
#[inline]
|
||||
fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
|
||||
self
|
||||
|
@ -107,13 +115,21 @@ impl<'env> Serializer for Ser<'env> {
|
|||
.map(|js_number| js_number.raw)
|
||||
}
|
||||
|
||||
#[cfg(all(any(napi2, napi3, napi4, napi5), not(napi6)))]
|
||||
#[cfg(all(
|
||||
any(
|
||||
feature = "napi2",
|
||||
feature = "napi3",
|
||||
feature = "napi4",
|
||||
feature = "napi5"
|
||||
),
|
||||
not(feature = "napi6")
|
||||
))]
|
||||
#[inline]
|
||||
fn serialize_u128(self, v: u128) -> Result<Self::Ok> {
|
||||
self.0.create_string(v.to_string().as_str()).map(|v| v.0)
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
#[inline]
|
||||
fn serialize_u128(self, v: u128) -> Result<Self::Ok> {
|
||||
let words_ref = &v as *const _;
|
||||
|
@ -124,13 +140,21 @@ impl<'env> Serializer for Ser<'env> {
|
|||
.map(|v| v.raw)
|
||||
}
|
||||
|
||||
#[cfg(all(any(napi2, napi3, napi4, napi5), not(napi6)))]
|
||||
#[cfg(all(
|
||||
any(
|
||||
feature = "napi2",
|
||||
feature = "napi3",
|
||||
feature = "napi4",
|
||||
feature = "napi5"
|
||||
),
|
||||
not(feature = "napi6")
|
||||
))]
|
||||
#[inline]
|
||||
fn serialize_i128(self, v: i128) -> Result<Self::Ok> {
|
||||
self.0.create_string(v.to_string().as_str()).map(|v| v.0)
|
||||
}
|
||||
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
#[inline]
|
||||
fn serialize_i128(self, v: i128) -> Result<Self::Ok> {
|
||||
let words_ref = &(v as u128) as *const _;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use crate::{sys, Error, Result, Status};
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
||||
pub enum ValueType {
|
||||
Unknown = 100,
|
||||
Undefined = 0,
|
||||
Null = 1,
|
||||
Boolean = 2,
|
||||
|
@ -15,8 +14,9 @@ pub enum ValueType {
|
|||
Object = 6,
|
||||
Function = 7,
|
||||
External = 8,
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
Bigint = 9,
|
||||
Unknown = 255,
|
||||
}
|
||||
|
||||
impl TryInto<sys::napi_valuetype> for ValueType {
|
||||
|
@ -25,7 +25,7 @@ impl TryInto<sys::napi_valuetype> for ValueType {
|
|||
fn try_into(self) -> Result<sys::napi_valuetype> {
|
||||
match self {
|
||||
ValueType::Unknown => Err(Error::from_status(Status::Unknown)),
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
ValueType::Bigint => Ok(sys::napi_valuetype::napi_bigint),
|
||||
ValueType::Boolean => Ok(sys::napi_valuetype::napi_boolean),
|
||||
ValueType::External => Ok(sys::napi_valuetype::napi_external),
|
||||
|
@ -40,23 +40,20 @@ impl TryInto<sys::napi_valuetype> for ValueType {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<sys::napi_valuetype> for ValueType {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: sys::napi_valuetype) -> Result<Self> {
|
||||
impl From<sys::napi_valuetype> for ValueType {
|
||||
fn from(value: sys::napi_valuetype) -> Self {
|
||||
match value {
|
||||
#[cfg(napi6)]
|
||||
sys::napi_valuetype::napi_bigint => Ok(ValueType::Bigint),
|
||||
sys::napi_valuetype::napi_boolean => Ok(ValueType::Boolean),
|
||||
sys::napi_valuetype::napi_external => Ok(ValueType::External),
|
||||
sys::napi_valuetype::napi_function => Ok(ValueType::Function),
|
||||
sys::napi_valuetype::napi_null => Ok(ValueType::Null),
|
||||
sys::napi_valuetype::napi_number => Ok(ValueType::Number),
|
||||
sys::napi_valuetype::napi_object => Ok(ValueType::Object),
|
||||
sys::napi_valuetype::napi_string => Ok(ValueType::String),
|
||||
sys::napi_valuetype::napi_symbol => Ok(ValueType::Symbol),
|
||||
sys::napi_valuetype::napi_undefined => Ok(ValueType::Undefined),
|
||||
_ => Err(Error::from_status(Status::Unknown)),
|
||||
#[cfg(feature = "napi6")]
|
||||
sys::napi_valuetype::napi_bigint => ValueType::Bigint,
|
||||
sys::napi_valuetype::napi_boolean => ValueType::Boolean,
|
||||
sys::napi_valuetype::napi_external => ValueType::External,
|
||||
sys::napi_valuetype::napi_function => ValueType::Function,
|
||||
sys::napi_valuetype::napi_null => ValueType::Null,
|
||||
sys::napi_valuetype::napi_number => ValueType::Number,
|
||||
sys::napi_valuetype::napi_object => ValueType::Object,
|
||||
sys::napi_valuetype::napi_string => ValueType::String,
|
||||
sys::napi_valuetype::napi_symbol => ValueType::Symbol,
|
||||
sys::napi_valuetype::napi_undefined => ValueType::Undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,23 +92,22 @@
|
|||
|
||||
mod async_work;
|
||||
mod call_context;
|
||||
#[cfg(feature = "napi3")]
|
||||
mod cleanup_env;
|
||||
mod env;
|
||||
mod error;
|
||||
mod js_values;
|
||||
mod module;
|
||||
#[cfg(all(feature = "libuv", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
mod promise;
|
||||
mod status;
|
||||
mod task;
|
||||
#[cfg(napi3)]
|
||||
#[cfg(feature = "napi3")]
|
||||
pub use cleanup_env::CleanupEnvHook;
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
pub mod threadsafe_function;
|
||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
mod tokio_rt;
|
||||
#[cfg(all(feature = "libuv", napi4))]
|
||||
mod uv;
|
||||
mod version;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod win_delay_load_hook;
|
||||
|
@ -124,7 +123,7 @@ pub use status::Status;
|
|||
pub use task::Task;
|
||||
pub use version::NodeVersion;
|
||||
|
||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
pub use tokio_rt::shutdown as shutdown_tokio_rt;
|
||||
|
||||
#[cfg(feature = "serde-json")]
|
||||
|
@ -147,7 +146,7 @@ pub type ContextlessResult<T> = Result<Option<T>>;
|
|||
macro_rules! register_module {
|
||||
($module_name:ident, $init:ident) => {
|
||||
#[inline]
|
||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
fn check_status(code: $crate::sys::napi_status) -> Result<()> {
|
||||
use $crate::{Error, Status};
|
||||
let status = Status::from(code);
|
||||
|
@ -163,7 +162,7 @@ macro_rules! register_module {
|
|||
use std::ptr;
|
||||
use $crate::{sys, Env, JsObject, NapiValue};
|
||||
|
||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
use $crate::shutdown_tokio_rt;
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -175,11 +174,11 @@ macro_rules! register_module {
|
|||
let mut exports: JsObject = JsObject::from_raw_unchecked(raw_env, raw_exports);
|
||||
let mut cjs_module = Module { env, exports };
|
||||
let result = $init(&mut cjs_module);
|
||||
#[cfg(all(feature = "tokio_rt", napi4))]
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
let hook_result = check_status(unsafe {
|
||||
sys::napi_add_env_cleanup_hook(raw_env, Some(shutdown_tokio_rt), ptr::null_mut())
|
||||
});
|
||||
#[cfg(not(all(feature = "tokio_rt", napi4)))]
|
||||
#[cfg(not(all(feature = "tokio_rt", feature = "napi4")))]
|
||||
let hook_result = Ok(());
|
||||
match hook_result.and_then(move |_| result) {
|
||||
Ok(_) => cjs_module.exports.raw(),
|
||||
|
|
|
@ -17,11 +17,11 @@ pub enum Status {
|
|||
EscapeCalledTwice,
|
||||
HandleScopeMismatch,
|
||||
CallbackScopeMismatch,
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
QueueFull,
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
Closing,
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
BigintExpected,
|
||||
Unknown,
|
||||
}
|
||||
|
@ -46,11 +46,11 @@ impl From<napi_status> for Status {
|
|||
napi_status::napi_escape_called_twice => EscapeCalledTwice,
|
||||
napi_status::napi_handle_scope_mismatch => HandleScopeMismatch,
|
||||
napi_status::napi_callback_scope_mismatch => CallbackScopeMismatch,
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
napi_status::napi_queue_full => QueueFull,
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
napi_status::napi_closing => Closing,
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
napi_status::napi_bigint_expected => BigintExpected,
|
||||
_ => Unknown,
|
||||
}
|
||||
|
@ -75,11 +75,11 @@ impl Into<self::napi_status> for Status {
|
|||
Self::EscapeCalledTwice => napi_status::napi_escape_called_twice,
|
||||
Self::HandleScopeMismatch => napi_status::napi_handle_scope_mismatch,
|
||||
Self::CallbackScopeMismatch => napi_status::napi_callback_scope_mismatch,
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
Self::QueueFull => napi_status::napi_queue_full,
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "napi4")]
|
||||
Self::Closing => napi_status::napi_closing,
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "napi6")]
|
||||
Self::BigintExpected => napi_status::napi_bigint_expected,
|
||||
Self::Unknown => napi_status::napi_generic_failure,
|
||||
}
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
extern crate alloc;
|
||||
|
||||
use alloc::alloc::{alloc, Layout};
|
||||
use futures::future::LocalBoxFuture;
|
||||
use futures::task::{waker, ArcWake, Context, Poll};
|
||||
use std::future::Future;
|
||||
use std::os::raw::c_void;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{sys, Error, Result, Status};
|
||||
|
||||
struct Task<'a> {
|
||||
future: LocalBoxFuture<'a, ()>,
|
||||
context: Context<'a>,
|
||||
}
|
||||
|
||||
struct UvWaker(*mut sys::uv_async_t);
|
||||
|
||||
unsafe impl Send for UvWaker {}
|
||||
unsafe impl Sync for UvWaker {}
|
||||
|
||||
impl UvWaker {
|
||||
fn new(event_loop: *mut sys::uv_loop_s) -> Result<UvWaker> {
|
||||
let uv_async_t = unsafe { alloc(Layout::new::<sys::uv_async_t>()) as *mut sys::uv_async_t };
|
||||
unsafe {
|
||||
let status = sys::uv_async_init(event_loop, uv_async_t, Some(poll_future));
|
||||
if status != 0 {
|
||||
return Err(Error::new(
|
||||
Status::Unknown,
|
||||
"Non-zero status returned from uv_async_init".to_owned(),
|
||||
));
|
||||
}
|
||||
};
|
||||
Ok(UvWaker(uv_async_t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assign_task(&self, mut task: Task) {
|
||||
if !task.poll_future() {
|
||||
let arc_task = Arc::new(task);
|
||||
unsafe {
|
||||
sys::uv_handle_set_data(
|
||||
self.0 as *mut sys::uv_handle_t,
|
||||
Arc::into_raw(arc_task) as *mut c_void,
|
||||
)
|
||||
};
|
||||
} else {
|
||||
unsafe { sys::uv_close(self.0 as *mut sys::uv_handle_t, None) };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl ArcWake for UvWaker {
|
||||
fn wake_by_ref(arc_self: &Arc<Self>) {
|
||||
let status = unsafe { sys::uv_async_send(arc_self.0) };
|
||||
assert!(status == 0, "wake_uv_async_by_ref failed");
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn execute(event_loop: *mut sys::uv_loop_s, future: LocalBoxFuture<()>) -> Result<()> {
|
||||
let uv_waker = UvWaker::new(event_loop)?;
|
||||
let arc_waker = Arc::new(uv_waker);
|
||||
let waker_to_poll = Arc::clone(&arc_waker);
|
||||
let waker = waker(arc_waker);
|
||||
let context = Context::from_waker(&waker);
|
||||
let task = Task { future, context };
|
||||
waker_to_poll.assign_task(task);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl<'a> Task<'a> {
|
||||
fn poll_future(&mut self) -> bool {
|
||||
let mut pinned = Pin::new(&mut self.future);
|
||||
let fut_mut = pinned.as_mut();
|
||||
match fut_mut.poll(&mut self.context) {
|
||||
Poll::Ready(_) => true,
|
||||
Poll::Pending => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn poll_future(handle: *mut sys::uv_async_t) {
|
||||
let data_ptr = sys::uv_handle_get_data(handle as *mut sys::uv_handle_t) as *mut Task;
|
||||
let mut task = Arc::from_raw(data_ptr);
|
||||
if let Some(mut_task) = Arc::get_mut(&mut task) {
|
||||
if mut_task.poll_future() {
|
||||
sys::uv_close(handle as *mut sys::uv_handle_t, None);
|
||||
} else {
|
||||
Arc::into_raw(task);
|
||||
};
|
||||
} else {
|
||||
Arc::into_raw(task);
|
||||
}
|
||||
}
|
|
@ -10,14 +10,14 @@ readme = "README.md"
|
|||
repository = "https://github.com/napi-rs/napi-rs"
|
||||
version = "0.4.7"
|
||||
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
tar = "0.4"
|
||||
[features]
|
||||
napi1 = []
|
||||
napi2 = ["napi1"]
|
||||
napi3 = ["napi2"]
|
||||
napi4 = ["napi3"]
|
||||
napi5 = ["napi4"]
|
||||
napi6 = ["napi5"]
|
||||
napi7 = ["napi6"]
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = {version = "0.55", default-features = false, features = ["logging", "runtime"]}
|
||||
glob = "0.3"
|
||||
regex = "1.3"
|
||||
semver = "0.11"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustc-args = ["--cfg", "napidocsrs"]
|
||||
napi-build = {version = "0.2", path = "../build"}
|
||||
|
|
125
sys/build.rs
125
sys/build.rs
|
@ -1,125 +0,0 @@
|
|||
extern crate bindgen;
|
||||
extern crate glob;
|
||||
extern crate semver;
|
||||
#[cfg(target_os = "windows")]
|
||||
extern crate tar;
|
||||
|
||||
use glob::glob;
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
#[cfg(not(any(target_os = "windows", napidocsrs)))]
|
||||
const NODE_PRINT_EXEC_PATH: &'static str = "console.log(process.execPath)";
|
||||
|
||||
fn main() {
|
||||
let node_full_version =
|
||||
String::from_utf8(Command::new("node").arg("-v").output().unwrap().stdout).unwrap();
|
||||
let node_version = semver::Version::parse(node_full_version.as_str().get(1..).unwrap()).unwrap();
|
||||
|
||||
let node_major_version = node_version.major;
|
||||
|
||||
println!("cargo:rerun-if-env-changed=NODE_INCLUDE_PATH");
|
||||
for entry in glob("./src/**/*.*").unwrap() {
|
||||
println!(
|
||||
"cargo:rerun-if-changed={}",
|
||||
entry.unwrap().to_str().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
if node_major_version < 8 && node_version.minor < 9 {
|
||||
panic!("node version is too low")
|
||||
}
|
||||
|
||||
let node_include_path_buf = find_node_include_path(node_full_version.trim_end());
|
||||
|
||||
let node_include_path = match env::var("NODE_INCLUDE_PATH") {
|
||||
Ok(node_include_path) => node_include_path,
|
||||
Err(_) => node_include_path_buf.to_str().unwrap().to_owned(),
|
||||
};
|
||||
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
|
||||
let mut sys_bindings_path = PathBuf::from("src");
|
||||
sys_bindings_path.push("bindings.h");
|
||||
|
||||
let mut bindgen_builder = bindgen::Builder::default()
|
||||
.derive_default(true)
|
||||
.header(sys_bindings_path.to_str().unwrap().to_owned())
|
||||
.clang_arg(format!("-I{}", node_include_path))
|
||||
.clang_arg("-target")
|
||||
.clang_arg(env::var("TARGET").unwrap());
|
||||
|
||||
if let Ok(uv_include_path) = env::var("NAPI_RS_INCLUDE_PATH") {
|
||||
bindgen_builder = bindgen_builder.clang_arg(format!("-I{}", uv_include_path));
|
||||
}
|
||||
if cfg!(target_os = "freebsd") {
|
||||
bindgen_builder = bindgen_builder.clang_arg(format!(
|
||||
"-I{}",
|
||||
node_include_path_buf.parent().unwrap().to_str().unwrap()
|
||||
));
|
||||
}
|
||||
|
||||
bindgen_builder
|
||||
.newtype_enum("(napi_|uv_).+")
|
||||
.whitelist_function("(napi_|uv_|extras_).+")
|
||||
.whitelist_type("(napi_|uv_|extras_).+")
|
||||
.generate()
|
||||
.expect("Unable to generate napi bindings")
|
||||
.write_to_file(out_path.join("bindings.rs"))
|
||||
.expect("Unable to write napi bindings");
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "windows", not(napidocsrs)))]
|
||||
fn find_node_include_path(node_full_version: &str) -> PathBuf {
|
||||
let mut out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
out_path.push(format!("node-headers-{}.tar.gz", node_full_version));
|
||||
let mut header_dist_path = PathBuf::from(&PathBuf::from(&out_path).parent().unwrap());
|
||||
let unpack_path = PathBuf::from(&header_dist_path);
|
||||
header_dist_path.push(format!("node-{}", node_full_version));
|
||||
header_dist_path.push("include");
|
||||
header_dist_path.push("node");
|
||||
if !header_dist_path.exists() {
|
||||
let script = r#"require('https').get(process.release.headersUrl, function (res) {
|
||||
res.pipe(require('zlib').createUnzip()).pipe(process.stdout)
|
||||
})"#;
|
||||
|
||||
let tar_binary = Command::new("node")
|
||||
.arg("-e")
|
||||
.arg(script)
|
||||
.output()
|
||||
.expect("Download headers file failed")
|
||||
.stdout;
|
||||
tar::Archive::new(tar_binary.as_slice())
|
||||
.unpack(&unpack_path)
|
||||
.expect("Unpack headers file failed");
|
||||
};
|
||||
header_dist_path
|
||||
}
|
||||
|
||||
#[cfg(napidocsrs)]
|
||||
fn find_node_include_path(_node_full_version: &str) -> PathBuf {
|
||||
let mut current = env::current_dir().unwrap();
|
||||
current.push(".node-headers");
|
||||
current
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "windows", napidocsrs)))]
|
||||
fn find_node_include_path(_node_full_version: &str) -> PathBuf {
|
||||
let node_exec_path = String::from_utf8(
|
||||
Command::new("node")
|
||||
.arg("-e")
|
||||
.arg(NODE_PRINT_EXEC_PATH)
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout,
|
||||
)
|
||||
.unwrap();
|
||||
PathBuf::from(node_exec_path)
|
||||
.parent()
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join("include/node")
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
#include <node_api.h>
|
||||
#include <uv.h>
|
1206
sys/src/lib.rs
1206
sys/src/lib.rs
File diff suppressed because it is too large
Load diff
|
@ -1,6 +0,0 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
|
@ -7,9 +7,13 @@ version = "0.1.0"
|
|||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[features]
|
||||
latest = ["napi/napi7"]
|
||||
napi3 = ["napi/napi3"]
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3"
|
||||
napi = {path = "../napi", features = ["libuv", "tokio_rt", "serde-json", "latin1"]}
|
||||
napi = {path = "../napi", features = ["tokio_rt", "serde-json", "latin1"]}
|
||||
napi-derive = {path = "../napi-derive"}
|
||||
serde = "1"
|
||||
serde_bytes = "0.11"
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
import { readFileSync } from 'fs'
|
||||
import { join, resolve } from 'path'
|
||||
|
||||
import test from 'ava'
|
||||
|
||||
import { napiVersion } from '../napi-version'
|
||||
|
||||
const bindings = require('../../index.node')
|
||||
|
||||
let threadMod: any
|
||||
|
||||
try {
|
||||
threadMod = require('worker_threads')
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
|
||||
const filepath = join(__dirname, './example.txt')
|
||||
|
||||
test('should execute future on libuv thread pool', async (t) => {
|
||||
if (napiVersion < 4) {
|
||||
t.is(bindings.uvReadFile, undefined)
|
||||
return
|
||||
}
|
||||
const fileContent = await bindings.uvReadFile(filepath)
|
||||
t.true(Buffer.isBuffer(fileContent))
|
||||
t.deepEqual(readFileSync(filepath), fileContent)
|
||||
})
|
||||
|
||||
if (threadMod && napiVersion >= 4) {
|
||||
test('should execute future on libuv thread pool of "Worker"', async (t) => {
|
||||
// Test in threads if current Node.js supports "worker_threads".`
|
||||
|
||||
const { Worker } = threadMod
|
||||
const script = resolve(__dirname, './uv_worker.js')
|
||||
const worker = new Worker(script)
|
||||
const success = await new Promise((resolve) => {
|
||||
worker.on('message', (success: boolean) => {
|
||||
resolve(success)
|
||||
})
|
||||
})
|
||||
|
||||
t.is(success, true)
|
||||
})
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
const { readFileSync } = require('fs')
|
||||
const { join } = require('path')
|
||||
const { isMainThread, parentPort } = require('worker_threads')
|
||||
|
||||
const bindings = require('../../index.node')
|
||||
|
||||
const filepath = join(__dirname, './example.txt')
|
||||
|
||||
if (!isMainThread) {
|
||||
;(async () => {
|
||||
const fileContent = await bindings.uvReadFile(filepath)
|
||||
const success =
|
||||
Buffer.isBuffer(fileContent) &&
|
||||
readFileSync(filepath).toString('utf8') === fileContent.toString('utf8')
|
||||
parentPort.postMessage(success)
|
||||
})().catch((e) => {
|
||||
throw e
|
||||
})
|
||||
}
|
|
@ -2,9 +2,11 @@
|
|||
"name": "test-module",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "cargo build && node ../scripts/index.js build",
|
||||
"build-aarch64": "cargo build --target aarch64-unknown-linux-gnu && node ../scripts/index.js build --target-triple aarch64-unknown-linux-gnu",
|
||||
"build-release": "cargo build --release && node ../scripts/index.js build --release",
|
||||
"build": "cargo build --features \"latest\" && node ../scripts/index.js build",
|
||||
"build-napi3": "cargo build --features \"napi3\" && node ../scripts/index.js build",
|
||||
"build-aarch64": "cargo build --features \"latest\" --target aarch64-unknown-linux-gnu && node ../scripts/index.js build --target-triple aarch64-unknown-linux-gnu",
|
||||
"build-i686": "cargo build --features \"latest\" --target i686-pc-windows-msvc && node ../scripts/index.js build --target-triple i686-pc-windows-msvc",
|
||||
"build-release": "cargo build --features \"latest\" --release && node ../scripts/index.js build --release",
|
||||
"test": "node ./index.js"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,17 +7,14 @@ extern crate serde_derive;
|
|||
|
||||
use napi::{Module, Result};
|
||||
|
||||
#[cfg(napi3)]
|
||||
mod cleanup_env;
|
||||
#[cfg(napi4)]
|
||||
mod libuv;
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "latest")]
|
||||
mod napi4;
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "latest")]
|
||||
mod napi5;
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "latest")]
|
||||
mod napi6;
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "latest")]
|
||||
mod tokio_rt;
|
||||
|
||||
mod array;
|
||||
|
@ -58,17 +55,14 @@ fn init(module: &mut Module) -> Result<()> {
|
|||
env::register_js(module)?;
|
||||
object::register_js(module)?;
|
||||
global::register_js(module)?;
|
||||
#[cfg(napi3)]
|
||||
cleanup_env::register_js(module)?;
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "latest")]
|
||||
napi4::register_js(module)?;
|
||||
#[cfg(napi4)]
|
||||
#[cfg(feature = "latest")]
|
||||
tokio_rt::register_js(module)?;
|
||||
#[cfg(napi4)]
|
||||
libuv::read_file::register_js(module)?;
|
||||
#[cfg(napi5)]
|
||||
#[cfg(feature = "latest")]
|
||||
napi5::register_js(module)?;
|
||||
#[cfg(napi6)]
|
||||
#[cfg(feature = "latest")]
|
||||
napi6::register_js(module)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
pub mod read_file;
|
|
@ -1,28 +0,0 @@
|
|||
use std::fs;
|
||||
use std::thread;
|
||||
|
||||
use futures::channel::oneshot;
|
||||
use futures::prelude::*;
|
||||
use napi::{CallContext, Error, JsObject, JsString, Module, Result, Status};
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn uv_read_file(ctx: CallContext) -> Result<JsObject> {
|
||||
let path = ctx.get::<JsString>(0)?;
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
let p = path.into_utf8()?.to_owned()?;
|
||||
thread::spawn(|| {
|
||||
let res = fs::read(p).map_err(|e| Error::new(Status::Unknown, format!("{}", e)));
|
||||
sender.send(res).expect("Send data failed");
|
||||
});
|
||||
ctx.env.execute(
|
||||
receiver
|
||||
.map_err(|e| Error::new(Status::Unknown, format!("{}", e)))
|
||||
.map(|x| x.and_then(|x| x)),
|
||||
|&mut env, data| env.create_buffer_with_data(data).map(|v| v.into_raw()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn register_js(module: &mut Module) -> Result<()> {
|
||||
module.create_named_method("uvReadFile", uv_read_file)?;
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue