commit
a540c8c07f
22 changed files with 366 additions and 21 deletions
2
.github/workflows/test.yaml
vendored
2
.github/workflows/test.yaml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: ['10', '12', '14', '15']
|
||||
node: ['12', '14', '16']
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
name: stable - ${{ matrix.os }} - node@${{ matrix.node }}
|
||||
|
|
38
README.md
38
README.md
|
@ -2,7 +2,7 @@
|
|||
|
||||
> This project was initialized from [xray](https://github.com/atom/xray)
|
||||
|
||||
A minimal library for building compiled `NodeJS` add-ons in `Rust`.
|
||||
A minimal library for building compiled `Node.js` add-ons in `Rust`.
|
||||
|
||||
<p>
|
||||
<a href="https://docs.rs/crate/napi"><img src="https://docs.rs/napi/badge.svg"></img></a>
|
||||
|
@ -22,17 +22,18 @@ A minimal library for building compiled `NodeJS` add-ons in `Rust`.
|
|||
![Windows i686](https://github.com/napi-rs/napi-rs/workflows/Windows%20i686/badge.svg)
|
||||
[![FreeBSD](https://api.cirrus-ci.com/github/napi-rs/napi-rs.svg)](https://cirrus-ci.com/github/napi-rs/napi-rs?branch=main)
|
||||
|
||||
## Operating Systems
|
||||
|
||||
| Linux | macOS | Windows | FreeBSD |
|
||||
| ----- | ----- | ------- | ------- |
|
||||
| ✓ | ✓ | ✓ | ✓ |
|
||||
|
||||
## Node.js
|
||||
|
||||
| Node10 | Node12 | Node14 | Node15 |
|
||||
| ------ | ------ | ------ | ------ |
|
||||
| ✓ | ✓ | ✓ | ✓ |
|
||||
| | node12 | node14 | node16 |
|
||||
| --------------------- | ------ | ------ | ------ |
|
||||
| Windows x64 | ✓ | ✓ | ✓ |
|
||||
| Windows x86 | ✓ | ✓ | ✓ |
|
||||
| macOS x64 | ✓ | ✓ | ✓ |
|
||||
| macOS aarch64 | ✓ | ✓ | ✓ |
|
||||
| Linux x64 gnu | ✓ | ✓ | ✓ |
|
||||
| Linux x64 musl | ✓ | ✓ | ✓ |
|
||||
| Linux aarch64 gnu | ✓ | ✓ | ✓ |
|
||||
| Linux arm gnueabihf | ✓ | ✓ | ✓ |
|
||||
| Linux aarch64 android | ✓ | ✓ | ✓ |
|
||||
| FreeBSD x64 | ✓ | ✓ | ✓ |
|
||||
|
||||
This library depends on N-API and requires `Node@10.0.0` or later.
|
||||
|
||||
|
@ -47,7 +48,7 @@ One nice feature is that this crate allows you to build add-ons purely with the
|
|||
### Define JavaScript functions
|
||||
|
||||
```rust
|
||||
#[js_function(1)] // ------> arguments length, omit for zero
|
||||
#[js_function(1)] // ------> arguments length
|
||||
fn fibonacci(ctx: CallContext) -> Result<JsNumber> {
|
||||
let n = ctx.get::<JsNumber>(0)?.try_into()?;
|
||||
ctx.env.create_int64(fibonacci_native(n))
|
||||
|
@ -108,11 +109,11 @@ name = "awesome"
|
|||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
napi = "1.0"
|
||||
napi-derive = "1.0"
|
||||
napi = "1"
|
||||
napi-derive = "1"
|
||||
|
||||
[build-dependencies]
|
||||
napi-build = "1.0"
|
||||
napi-build = "1"
|
||||
```
|
||||
|
||||
And create `build.rs` in your own project:
|
||||
|
@ -209,6 +210,9 @@ yarn test
|
|||
| [napi_create_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_create_string_latin1) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_create_string_utf16](https://nodejs.org/api/n-api.html#n_api_napi_create_string_utf16) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_create_string_utf8](https://nodejs.org/api/n-api.html#n_api_napi_create_string_utf8) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_type_tag](https://nodejs.org/api/n-api.html#n_api_napi_type_tag) | 8 | v14.8.0, v12.19.0 | ⚠️ |
|
||||
|
||||
> I have no plan to implement `nape_type_tag` and related API in `napi-rs`, because we have implemented a `rust` replacement in [TaggedObject](https://github.com/napi-rs/napi-rs/blob/main/napi/src/js_values/tagged_object.rs) which is more convenient and more compatible.
|
||||
|
||||
### [Functions to convert from N-API to C types](https://nodejs.org/api/n-api.html#n_api_functions_to_convert_from_n_api_to_c_types)
|
||||
|
||||
|
@ -258,3 +262,5 @@ yarn test
|
|||
| [napi_strict_equals](https://nodejs.org/api/n-api.html#n_api_napi_strict_equals) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_detach_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_detach_arraybuffer) | 7 | v13.3.0 | ✅ |
|
||||
| [napi_is_detached_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_is_detached_arraybuffer) | 7 | v13.3.0 | ✅ |
|
||||
| [napi_object_freeze](https://nodejs.org/api/n-api.html#n_api_napi_object_freeze) | 8 | v14.14.0, v12.20.0 | ✅ |
|
||||
| [napi_object_seal](https://nodejs.org/api/n-api.html#n_api_napi_object_seal) | 8 | v14.14.0, v12.20.0 | ✅ |
|
||||
|
|
|
@ -19,6 +19,7 @@ napi4 = ["napi3", "napi-sys/napi4"]
|
|||
napi5 = ["napi4", "napi-sys/napi5"]
|
||||
napi6 = ["napi5", "napi-sys/napi6"]
|
||||
napi7 = ["napi6", "napi-sys/napi7"]
|
||||
napi8 = ["napi7", "napi-sys/napi8"]
|
||||
serde-json = ["serde", "serde_json"]
|
||||
tokio_rt = ["futures", "tokio", "once_cell", "napi4"]
|
||||
|
||||
|
|
28
napi/src/async_cleanup_hook.rs
Normal file
28
napi/src/async_cleanup_hook.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use std::mem;
|
||||
|
||||
use crate::{sys, Status};
|
||||
|
||||
/// Notice
|
||||
/// The hook will be removed if `AsyncCleanupHook` was `dropped`.
|
||||
/// If you want keep the hook until node process exited, call the `AsyncCleanupHook::forget`.
|
||||
#[repr(transparent)]
|
||||
pub struct AsyncCleanupHook(pub(crate) sys::napi_async_cleanup_hook_handle);
|
||||
|
||||
impl AsyncCleanupHook {
|
||||
/// Safe to forget it.
|
||||
/// Things will be cleanup before process exited.
|
||||
pub fn forget(self) {
|
||||
mem::forget(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for AsyncCleanupHook {
|
||||
fn drop(&mut self) {
|
||||
let status = unsafe { sys::napi_remove_async_cleanup_hook(self.0) };
|
||||
assert!(
|
||||
status == sys::Status::napi_ok,
|
||||
"Delete async cleanup hook failed: {}",
|
||||
Status::from(status)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -14,8 +14,10 @@ use crate::{
|
|||
Error, ExtendedErrorInfo, NodeVersion, Result, Status,
|
||||
};
|
||||
|
||||
#[cfg(feature = "napi8")]
|
||||
use crate::async_cleanup_hook::AsyncCleanupHook;
|
||||
#[cfg(feature = "napi3")]
|
||||
use super::cleanup_env::{CleanupEnvHook, CleanupEnvHookData};
|
||||
use crate::cleanup_env::{CleanupEnvHook, CleanupEnvHookData};
|
||||
#[cfg(all(feature = "serde-json"))]
|
||||
use crate::js_values::{De, Ser};
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
|
@ -1191,6 +1193,58 @@ impl Env {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi8")]
|
||||
/// Registers hook, which is a function of type `FnOnce(Arg)`, as a function to be run with the `arg` parameter once the current Node.js environment exits.
|
||||
///
|
||||
/// Unlike [`add_env_cleanup_hook`](https://docs.rs/napi/latest/napi/struct.Env.html#method.add_env_cleanup_hook), the hook is allowed to be asynchronous.
|
||||
///
|
||||
/// Otherwise, behavior generally matches that of [`add_env_cleanup_hook`](https://docs.rs/napi/latest/napi/struct.Env.html#method.add_env_cleanup_hook).
|
||||
pub fn add_removable_async_cleanup_hook<Arg, F>(
|
||||
&self,
|
||||
arg: Arg,
|
||||
cleanup_fn: F,
|
||||
) -> Result<AsyncCleanupHook>
|
||||
where
|
||||
F: FnOnce(Arg),
|
||||
Arg: 'static,
|
||||
{
|
||||
let mut handle = ptr::null_mut();
|
||||
check_status!(unsafe {
|
||||
sys::napi_add_async_cleanup_hook(
|
||||
self.0,
|
||||
Some(
|
||||
async_finalize::<Arg, F>
|
||||
as unsafe extern "C" fn(handle: sys::napi_async_cleanup_hook_handle, data: *mut c_void),
|
||||
),
|
||||
Box::leak(Box::new((arg, cleanup_fn))) as *mut (Arg, F) as *mut c_void,
|
||||
&mut handle,
|
||||
)
|
||||
})?;
|
||||
Ok(AsyncCleanupHook(handle))
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi8")]
|
||||
/// This API is very similar to [`add_removable_async_cleanup_hook`](https://docs.rs/napi/latest/napi/struct.Env.html#method.add_removable_async_cleanup_hook)
|
||||
///
|
||||
/// Use this one if you don't want remove the cleanup hook anymore.
|
||||
pub fn add_async_cleanup_hook<Arg, F>(&self, arg: Arg, cleanup_fn: F) -> Result<()>
|
||||
where
|
||||
F: FnOnce(Arg),
|
||||
Arg: 'static,
|
||||
{
|
||||
check_status!(unsafe {
|
||||
sys::napi_add_async_cleanup_hook(
|
||||
self.0,
|
||||
Some(
|
||||
async_finalize::<Arg, F>
|
||||
as unsafe extern "C" fn(handle: sys::napi_async_cleanup_hook_handle, data: *mut c_void),
|
||||
),
|
||||
Box::leak(Box::new((arg, cleanup_fn))) as *mut (Arg, F) as *mut c_void,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// # Serialize `Rust Struct` into `JavaScript Value`
|
||||
///
|
||||
/// ```
|
||||
|
@ -1341,3 +1395,22 @@ unsafe extern "C" fn raw_finalize_with_custom_callback<Hint, Finalize>(
|
|||
let (hint, callback) = *Box::from_raw(finalize_hint as *mut (Hint, Finalize));
|
||||
callback(hint, Env::from_raw(env));
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi8")]
|
||||
unsafe extern "C" fn async_finalize<Arg, F>(
|
||||
handle: sys::napi_async_cleanup_hook_handle,
|
||||
data: *mut c_void,
|
||||
) where
|
||||
Arg: 'static,
|
||||
F: FnOnce(Arg),
|
||||
{
|
||||
let (arg, callback) = *Box::from_raw(data as *mut (Arg, F));
|
||||
callback(arg);
|
||||
if !handle.is_null() {
|
||||
let status = sys::napi_remove_async_cleanup_hook(handle);
|
||||
assert!(
|
||||
status == sys::Status::napi_ok,
|
||||
"Remove async cleanup hook failed after async cleanup callback"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,6 +239,18 @@ macro_rules! impl_js_value_methods {
|
|||
})?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi8")]
|
||||
#[inline]
|
||||
pub fn freeze(&mut self) -> Result<()> {
|
||||
check_status!(unsafe { sys::napi_object_freeze(self.0.env, self.0.value) })
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi8")]
|
||||
#[inline]
|
||||
pub fn seal(&mut self) -> Result<()> {
|
||||
check_status!(unsafe { sys::napi_object_seal(self.0.env, self.0.value) })
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
//!
|
||||
//! ## Feature flags
|
||||
//!
|
||||
//! ### napi1 ~ napi7
|
||||
//! ### napi1 ~ napi8
|
||||
//!
|
||||
//! Because `NodeJS` N-API has versions. So there are feature flags to choose what version of `N-API` you want to build for.
|
||||
//! For example, if you want build a library which can be used by `node@10.17.0`, you should choose the `napi5` or lower.
|
||||
|
@ -75,6 +75,10 @@
|
|||
//! ```
|
||||
//!
|
||||
|
||||
#[cfg(feature = "napi8")]
|
||||
mod async_cleanup_hook;
|
||||
#[cfg(feature = "napi8")]
|
||||
pub use async_cleanup_hook::AsyncCleanupHook;
|
||||
mod async_work;
|
||||
mod call_context;
|
||||
#[cfg(feature = "napi3")]
|
||||
|
|
|
@ -29,7 +29,7 @@ pub enum Status {
|
|||
ArrayBufferExpected,
|
||||
DetachableArraybufferExpected,
|
||||
WouldDeadlock,
|
||||
Unknown = 1024, // unknown status. for example, using napi3 module in napi7 NodeJS, and generate an invalid napi3 status
|
||||
Unknown = 1024, // unknown status. for example, using napi3 module in napi7 Node.js, and generate an invalid napi3 status
|
||||
}
|
||||
|
||||
impl Display for Status {
|
||||
|
|
|
@ -18,3 +18,4 @@ napi4 = ["napi3"]
|
|||
napi5 = ["napi4"]
|
||||
napi6 = ["napi5"]
|
||||
napi7 = ["napi6"]
|
||||
napi8 = ["napi7"]
|
||||
|
|
|
@ -181,6 +181,18 @@ pub enum napi_key_conversion {
|
|||
napi_key_numbers_to_strings,
|
||||
}
|
||||
|
||||
#[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)>;
|
||||
|
||||
extern "C" {
|
||||
pub fn napi_get_last_error_info(
|
||||
env: napi_env,
|
||||
|
@ -801,6 +813,25 @@ extern "C" {
|
|||
result: *mut bool,
|
||||
) -> napi_status;
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi8")]
|
||||
extern "C" {
|
||||
pub 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;
|
||||
|
||||
pub fn napi_remove_async_cleanup_hook(
|
||||
remove_handle: napi_async_cleanup_hook_handle,
|
||||
) -> napi_status;
|
||||
|
||||
pub fn napi_object_freeze(env: napi_env, object: napi_value) -> napi_status;
|
||||
|
||||
pub fn napi_object_seal(env: napi_env, object: napi_value) -> napi_status;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct napi_callback_scope__ {
|
||||
|
|
|
@ -8,7 +8,7 @@ version = "0.1.0"
|
|||
crate-type = ["cdylib"]
|
||||
|
||||
[features]
|
||||
latest = ["napi/napi7"]
|
||||
latest = ["napi/napi8"]
|
||||
napi3 = ["napi/napi3"]
|
||||
|
||||
[dependencies]
|
||||
|
|
33
test_module/__test__/napi7/arraybuffer.spec.ts
Normal file
33
test_module/__test__/napi7/arraybuffer.spec.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import ava from 'ava'
|
||||
|
||||
import { napiVersion } from '../napi-version'
|
||||
|
||||
const bindings = require('../../index.node')
|
||||
|
||||
const test = napiVersion >= 7 ? ava : ava.skip
|
||||
|
||||
test('should be able to detach ArrayBuffer', (t) => {
|
||||
const buf = Buffer.from('hello world')
|
||||
const ab = buf.buffer.slice(0, buf.length)
|
||||
try {
|
||||
bindings.testDetachArrayBuffer(ab)
|
||||
t.is(ab.byteLength, 0)
|
||||
} catch (e) {
|
||||
t.is(e.code, 'DetachableArraybufferExpected')
|
||||
}
|
||||
})
|
||||
|
||||
test('is detached arraybuffer should work fine', (t) => {
|
||||
const buf = Buffer.from('hello world')
|
||||
const ab = buf.buffer.slice(0, buf.length)
|
||||
try {
|
||||
bindings.testDetachArrayBuffer(ab)
|
||||
const nonDetachedArrayBuffer = new ArrayBuffer(10)
|
||||
const detachedArrayBuffer = new ArrayBuffer(0)
|
||||
t.true(bindings.testIsDetachedArrayBuffer(ab))
|
||||
t.false(bindings.testIsDetachedArrayBuffer(nonDetachedArrayBuffer))
|
||||
t.true(bindings.testIsDetachedArrayBuffer(detachedArrayBuffer))
|
||||
} catch (e) {
|
||||
t.is(e.code, 'DetachableArraybufferExpected')
|
||||
}
|
||||
})
|
28
test_module/__test__/napi8/async-cleanup.spec.ts
Normal file
28
test_module/__test__/napi8/async-cleanup.spec.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { execSync } from 'child_process'
|
||||
import { join } from 'path'
|
||||
|
||||
import ava from 'ava'
|
||||
|
||||
import { napiVersion } from '../napi-version'
|
||||
|
||||
const bindings = require('../../index.node')
|
||||
|
||||
const test = napiVersion >= 8 ? ava : ava.skip
|
||||
|
||||
test('should be able to add async cleanup hook', (t) => {
|
||||
const output = execSync(
|
||||
`node ${join(__dirname, 'sub-process.js')}`,
|
||||
).toString()
|
||||
t.is(output.trim(), 'Exit from sub process')
|
||||
})
|
||||
|
||||
test('should be able to add removable async cleanup hook', (t) => {
|
||||
const output = execSync(
|
||||
`node ${join(__dirname, 'sub-process-removable.js')}`,
|
||||
).toString()
|
||||
t.is(output.trim(), 'Exit from sub process')
|
||||
})
|
||||
|
||||
test('should be able to remove cleanup hook after added', (t) => {
|
||||
t.notThrows(() => bindings.testRemoveAsyncCleanupHook())
|
||||
})
|
25
test_module/__test__/napi8/object.spec.ts
Normal file
25
test_module/__test__/napi8/object.spec.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import ava from 'ava'
|
||||
|
||||
import { napiVersion } from '../napi-version'
|
||||
|
||||
const bindings = require('../../index.node')
|
||||
|
||||
const test = napiVersion >= 8 ? ava : ava.skip
|
||||
|
||||
test('should be able to freeze object', (t) => {
|
||||
const obj: any = {}
|
||||
bindings.testFreezeObject(obj)
|
||||
t.true(Object.isFrozen(obj))
|
||||
t.throws(() => {
|
||||
obj.a = 1
|
||||
})
|
||||
})
|
||||
|
||||
test('should be able to seal object', (t) => {
|
||||
const obj: any = {}
|
||||
bindings.testSealObject(obj)
|
||||
t.true(Object.isSealed(obj))
|
||||
t.throws(() => {
|
||||
obj.a = 1
|
||||
})
|
||||
})
|
3
test_module/__test__/napi8/sub-process-removable.js
Normal file
3
test_module/__test__/napi8/sub-process-removable.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
const bindings = require('../../index.node')
|
||||
|
||||
bindings.testAddRemovableAsyncCleanupHook()
|
3
test_module/__test__/napi8/sub-process.js
Normal file
3
test_module/__test__/napi8/sub-process.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
const bindings = require('../../index.node')
|
||||
|
||||
bindings.testAddAsyncCleanupHook()
|
|
@ -13,6 +13,10 @@ mod napi5;
|
|||
#[cfg(feature = "latest")]
|
||||
mod napi6;
|
||||
#[cfg(feature = "latest")]
|
||||
mod napi7;
|
||||
#[cfg(feature = "latest")]
|
||||
mod napi8;
|
||||
#[cfg(feature = "latest")]
|
||||
mod tokio_rt;
|
||||
|
||||
mod array;
|
||||
|
@ -61,5 +65,9 @@ fn init(mut exports: JsObject, env: Env) -> Result<()> {
|
|||
napi5::register_js(&mut exports)?;
|
||||
#[cfg(feature = "latest")]
|
||||
napi6::register_js(&mut exports)?;
|
||||
#[cfg(feature = "latest")]
|
||||
napi7::register_js(&mut exports)?;
|
||||
#[cfg(feature = "latest")]
|
||||
napi8::register_js(&mut exports)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
14
test_module/src/napi7/buffer.rs
Normal file
14
test_module/src/napi7/buffer.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use napi::*;
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn detach_arraybuffer(ctx: CallContext) -> Result<JsUndefined> {
|
||||
let input = ctx.get::<JsArrayBuffer>(0)?;
|
||||
input.detach()?;
|
||||
ctx.env.get_undefined()
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn is_detach_arraybuffer(ctx: CallContext) -> Result<JsBoolean> {
|
||||
let input = ctx.get::<JsArrayBuffer>(0)?;
|
||||
ctx.env.get_boolean(input.is_detached()?)
|
||||
}
|
11
test_module/src/napi7/mod.rs
Normal file
11
test_module/src/napi7/mod.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
use napi::{JsObject, Result};
|
||||
|
||||
mod buffer;
|
||||
|
||||
use buffer::*;
|
||||
|
||||
pub fn register_js(exports: &mut JsObject) -> Result<()> {
|
||||
exports.create_named_method("testDetachArrayBuffer", detach_arraybuffer)?;
|
||||
exports.create_named_method("testIsDetachedArrayBuffer", is_detach_arraybuffer)?;
|
||||
Ok(())
|
||||
}
|
30
test_module/src/napi8/async_cleanup.rs
Normal file
30
test_module/src/napi8/async_cleanup.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use napi::*;
|
||||
|
||||
#[js_function]
|
||||
pub fn add_removable_async_cleanup_hook(ctx: CallContext) -> Result<JsUndefined> {
|
||||
let cleanup_hook = ctx
|
||||
.env
|
||||
.add_removable_async_cleanup_hook(1u32, |_arg: u32| {
|
||||
println!("Exit from sub process");
|
||||
})?;
|
||||
cleanup_hook.forget();
|
||||
ctx.env.get_undefined()
|
||||
}
|
||||
|
||||
#[js_function]
|
||||
pub fn add_async_cleanup_hook(ctx: CallContext) -> Result<JsUndefined> {
|
||||
ctx.env.add_async_cleanup_hook(1u32, |_arg: u32| {
|
||||
println!("Exit from sub process");
|
||||
})?;
|
||||
ctx.env.get_undefined()
|
||||
}
|
||||
|
||||
#[js_function]
|
||||
pub fn remove_async_cleanup_hook(ctx: CallContext) -> Result<JsUndefined> {
|
||||
ctx
|
||||
.env
|
||||
.add_removable_async_cleanup_hook(1u32, |_arg: u32| {
|
||||
println!("Exit from sub process");
|
||||
})?;
|
||||
ctx.env.get_undefined()
|
||||
}
|
19
test_module/src/napi8/mod.rs
Normal file
19
test_module/src/napi8/mod.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use napi::{JsObject, Result};
|
||||
|
||||
mod async_cleanup;
|
||||
mod object;
|
||||
|
||||
use async_cleanup::*;
|
||||
use object::*;
|
||||
|
||||
pub fn register_js(exports: &mut JsObject) -> Result<()> {
|
||||
exports.create_named_method("testSealObject", seal_object)?;
|
||||
exports.create_named_method("testFreezeObject", freeze_object)?;
|
||||
exports.create_named_method(
|
||||
"testAddRemovableAsyncCleanupHook",
|
||||
add_removable_async_cleanup_hook,
|
||||
)?;
|
||||
exports.create_named_method("testRemoveAsyncCleanupHook", remove_async_cleanup_hook)?;
|
||||
exports.create_named_method("testAddAsyncCleanupHook", add_async_cleanup_hook)?;
|
||||
Ok(())
|
||||
}
|
15
test_module/src/napi8/object.rs
Normal file
15
test_module/src/napi8/object.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use napi::*;
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn seal_object(ctx: CallContext) -> Result<JsUndefined> {
|
||||
let mut obj: JsObject = ctx.get(0)?;
|
||||
obj.seal()?;
|
||||
ctx.env.get_undefined()
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn freeze_object(ctx: CallContext) -> Result<JsUndefined> {
|
||||
let mut obj: JsObject = ctx.get(0)?;
|
||||
obj.freeze()?;
|
||||
ctx.env.get_undefined()
|
||||
}
|
Loading…
Reference in a new issue