refactor(napi): async and lifetime span
This commit is contained in:
parent
25296d8d84
commit
1a280aa30f
24 changed files with 1645 additions and 462 deletions
2
.prettierignore
Normal file
2
.prettierignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
target
|
||||||
|
node_modules
|
88
README.md
88
README.md
|
@ -27,6 +27,7 @@ This library depends on N-API and requires Node 8.9 or later. It is still pretty
|
||||||
One nice feature is that this crate allows you to build add-ons purely with the Rust toolchain and without involving `node-gyp`.
|
One nice feature is that this crate allows you to build add-ons purely with the Rust toolchain and without involving `node-gyp`.
|
||||||
|
|
||||||
## Taste
|
## Taste
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#[js_function(1)] // ------> arguments length, omit for zero
|
#[js_function(1)] // ------> arguments length, omit for zero
|
||||||
fn fibonacci(ctx: CallContext) -> Result<Value<Number>> {
|
fn fibonacci(ctx: CallContext) -> Result<Value<Number>> {
|
||||||
|
@ -62,7 +63,7 @@ napi-build = "0.1"
|
||||||
|
|
||||||
And create `build.rs` in your own project:
|
And create `build.rs` in your own project:
|
||||||
|
|
||||||
```rs
|
```rust
|
||||||
// build.rs
|
// build.rs
|
||||||
extern crate napi_build;
|
extern crate napi_build;
|
||||||
|
|
||||||
|
@ -78,7 +79,6 @@ See the included [test_module](./test_module) for an example add-on.
|
||||||
Run `cargo build` to produce the `Dynamic lib` file. And install the `napi-rs` to help you copy `Dynamic lib` file to `.node` file in case you can `require` it in your program.
|
Run `cargo build` to produce the `Dynamic lib` file. And install the `napi-rs` to help you copy `Dynamic lib` file to `.node` file in case you can `require` it in your program.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
||||||
{
|
{
|
||||||
"package": "your pkg",
|
"package": "your pkg",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -128,7 +128,7 @@ npm test
|
||||||
### Create JavaScript values
|
### Create JavaScript values
|
||||||
|
|
||||||
| NAPI | NAPI Version | Minimal Node version | Status |
|
| NAPI | NAPI Version | Minimal Node version | Status |
|
||||||
| ------------------------------------------------------------ | ------------ | -------------------- | ------ |
|
| ------------------------------------------------------------------------------------------------------------ | ------------ | -------------------- | ------ |
|
||||||
| [Enum types](https://nodejs.org/api/n-api.html#n_api_enum_types) | 6 | v13.7.0 | ⛔️ |
|
| [Enum types](https://nodejs.org/api/n-api.html#n_api_enum_types) | 6 | v13.7.0 | ⛔️ |
|
||||||
| [napi_create_array](https://nodejs.org/api/n-api.html#n_api_napi_create_array) | 1 | v8.0.0 | ✅ |
|
| [napi_create_array](https://nodejs.org/api/n-api.html#n_api_napi_create_array) | 1 | v8.0.0 | ✅ |
|
||||||
| [napi_create_array_with_length](https://nodejs.org/api/n-api.html#n_api_napi_create_array_with_length) | 1 | v8.0.0 | ✅ |
|
| [napi_create_array_with_length](https://nodejs.org/api/n-api.html#n_api_napi_create_array_with_length) | 1 | v8.0.0 | ✅ |
|
||||||
|
@ -157,48 +157,48 @@ npm test
|
||||||
### [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)
|
### [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)
|
||||||
|
|
||||||
| NAPI | NAPI Version | Minimal Node Version | Status |
|
| NAPI | NAPI Version | Minimal Node Version | Status |
|
||||||
| ---- | ------------ | -------------------- | ------ |
|
| ---------------------------------------------------------------------------------------------------- | ------------ | -------------------- | ------ |
|
||||||
|[napi_get_array_length](https://nodejs.org/api/n-api.html#n_api_napi_get_array_length)| 1 | v8.0.0 | ✅ |
|
| [napi_get_array_length](https://nodejs.org/api/n-api.html#n_api_napi_get_array_length) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_arraybuffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_arraybuffer_info)| 1 | v8.0.0 | ✅ |
|
| [napi_get_arraybuffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_arraybuffer_info) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_buffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_buffer_info)| 1 | v8.0.0 | ✅ |
|
| [napi_get_buffer_info](https://nodejs.org/api/n-api.html#n_api_napi_get_buffer_info) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_prototype](https://nodejs.org/api/n-api.html#n_api_napi_get_prototype)| 1 | v8.0.0 | ⛔️ |
|
| [napi_get_prototype](https://nodejs.org/api/n-api.html#n_api_napi_get_prototype) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_get_typedarray_info](https://nodejs.org/api/n-api.html#n_api_napi_get_typedarray_info)| 1 | v8.0.0 | ⛔️ |
|
| [napi_get_typedarray_info](https://nodejs.org/api/n-api.html#n_api_napi_get_typedarray_info) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_get_dataview_info](https://nodejs.org/api/n-api.html#n_api_napi_get_dataview_info)| 1 | v8.3.0 | ⛔️ |
|
| [napi_get_dataview_info](https://nodejs.org/api/n-api.html#n_api_napi_get_dataview_info) | 1 | v8.3.0 | ⛔️ |
|
||||||
|[napi_get_date_value](https://nodejs.org/api/n-api.html#n_api_napi_get_date_value)| 5 | v11.11.0 | ⛔️ |
|
| [napi_get_date_value](https://nodejs.org/api/n-api.html#n_api_napi_get_date_value) | 5 | v11.11.0 | ⛔️ |
|
||||||
|[napi_get_value_bool](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bool)| 1 | v8.0.0 | ✅ |
|
| [napi_get_value_bool](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bool) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_value_double](https://nodejs.org/api/n-api.html#n_api_napi_get_value_double)| 1 | v8.0.0 | ✅ |
|
| [napi_get_value_double](https://nodejs.org/api/n-api.html#n_api_napi_get_value_double) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_value_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_int64)| 6 | v10.7.0 | ⛔️ |
|
| [napi_get_value_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_int64) | 6 | v10.7.0 | ⛔️ |
|
||||||
|[napi_get_value_bigint_uint64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_uint64)| 6 | v10.7.0 | ⛔️ |
|
| [napi_get_value_bigint_uint64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_uint64) | 6 | v10.7.0 | ⛔️ |
|
||||||
|[napi_get_value_bigint_words](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_words)| 6 | v10.7.0 | ⛔️ |
|
| [napi_get_value_bigint_words](https://nodejs.org/api/n-api.html#n_api_napi_get_value_bigint_words) | 6 | v10.7.0 | ⛔️ |
|
||||||
|[napi_get_value_external](https://nodejs.org/api/n-api.html#n_api_napi_get_value_external)| 1 | v8.0.0 | ⛔️ |
|
| [napi_get_value_external](https://nodejs.org/api/n-api.html#n_api_napi_get_value_external) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_get_value_int32](https://nodejs.org/api/n-api.html#n_api_napi_get_value_int32)| 1 | v8.0.0 | ✅ |
|
| [napi_get_value_int32](https://nodejs.org/api/n-api.html#n_api_napi_get_value_int32) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_value_int64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_int64)| 1 | v8.0.0 | ✅ |
|
| [napi_get_value_int64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_int64) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_value_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_latin1)| 1 | v8.0.0 | ⛔️ |
|
| [napi_get_value_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_latin1) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_get_value_string_utf8](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_utf8)| 1 | v8.0.0 | ✅ |
|
| [napi_get_value_string_utf8](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_utf8) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_value_string_utf16](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_utf16)| 1 | v8.0.0 | ✅ |
|
| [napi_get_value_string_utf16](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_utf16) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_value_uint32](https://nodejs.org/api/n-api.html#n_api_napi_get_value_uint32)| 1 | v8.0.0 | ✅ |
|
| [napi_get_value_uint32](https://nodejs.org/api/n-api.html#n_api_napi_get_value_uint32) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_boolean](https://nodejs.org/api/n-api.html#n_api_napi_get_boolean)| 1 | v8.0.0 | ✅ |
|
| [napi_get_boolean](https://nodejs.org/api/n-api.html#n_api_napi_get_boolean) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_global](https://nodejs.org/api/n-api.html#n_api_napi_get_global)| 1 | v8.0.0 | ⛔️ |
|
| [napi_get_global](https://nodejs.org/api/n-api.html#n_api_napi_get_global) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_get_null](https://nodejs.org/api/n-api.html#n_api_napi_get_null)| 1 | v8.0.0 | ✅ |
|
| [napi_get_null](https://nodejs.org/api/n-api.html#n_api_napi_get_null) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_get_undefined](https://nodejs.org/api/n-api.html#n_api_napi_get_undefined)| 1 | v8.0.0 | ✅ |
|
| [napi_get_undefined](https://nodejs.org/api/n-api.html#n_api_napi_get_undefined) | 1 | v8.0.0 | ✅ |
|
||||||
|
|
||||||
### [Working with JavaScript Values and Abstract Operations](https://nodejs.org/api/n-api.html#n_api_working_with_javascript_values_and_abstract_operations)
|
### [Working with JavaScript Values and Abstract Operations](https://nodejs.org/api/n-api.html#n_api_working_with_javascript_values_and_abstract_operations)
|
||||||
|
|
||||||
| NAPI | NAPI Version | Minimal Node Version | Status |
|
| NAPI | NAPI Version | Minimal Node Version | Status |
|
||||||
| ---- | ------------ | -------------------- | ------ |
|
| ---------------------------------------------------------------------------------------------------- | ------------ | -------------------- | ------ |
|
||||||
|[napi_coerce_to_bool](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_bool)| 1 | v8.0.0 | ✅ |
|
| [napi_coerce_to_bool](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_bool) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_coerce_to_number](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_number)| 1 | v8.0.0 | ✅ |
|
| [napi_coerce_to_number](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_number) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_coerce_to_object](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_object)| 1 | v8.0.0 | ✅ |
|
| [napi_coerce_to_object](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_object) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_coerce_to_string](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_string)| 1 | v8.0.0 | ✅ |
|
| [napi_coerce_to_string](https://nodejs.org/api/n-api.html#n_api_napi_coerce_to_string) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_typeof](https://nodejs.org/api/n-api.html#n_api_napi_typeof)| 1 | v8.0.0 | ✅ |
|
| [napi_typeof](https://nodejs.org/api/n-api.html#n_api_napi_typeof) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_instanceof](https://nodejs.org/api/n-api.html#n_api_napi_instanceof)| 1 | v8.0.0 | ⛔️ |
|
| [napi_instanceof](https://nodejs.org/api/n-api.html#n_api_napi_instanceof) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_is_array](https://nodejs.org/api/n-api.html#n_api_napi_is_array)| 1 | v8.0.0 | ✅ |
|
| [napi_is_array](https://nodejs.org/api/n-api.html#n_api_napi_is_array) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_is_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_is_arraybuffer)| 1 | v8.0.0 | ✅ |
|
| [napi_is_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_is_arraybuffer) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_is_buffer](https://nodejs.org/api/n-api.html#n_api_napi_is_buffer)| 1 | v8.0.0 | ✅ |
|
| [napi_is_buffer](https://nodejs.org/api/n-api.html#n_api_napi_is_buffer) | 1 | v8.0.0 | ✅ |
|
||||||
|[napi_is_date](https://nodejs.org/api/n-api.html#n_api_napi_is_date)| 1 | v8.0.0 | ⛔️ |
|
| [napi_is_date](https://nodejs.org/api/n-api.html#n_api_napi_is_date) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_is_error](https://nodejs.org/api/n-api.html#n_api_napi_is_error_1)| 1 | v8.0.0 | ⛔️ |
|
| [napi_is_error](https://nodejs.org/api/n-api.html#n_api_napi_is_error_1) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_is_typedarray](https://nodejs.org/api/n-api.html#n_api_napi_is_typedarray)| 1 | v8.0.0 | ⛔️ |
|
| [napi_is_typedarray](https://nodejs.org/api/n-api.html#n_api_napi_is_typedarray) | 1 | v8.0.0 | ⛔️ |
|
||||||
|[napi_is_dataview](https://nodejs.org/api/n-api.html#n_api_napi_is_dataview)| 1 | v8.3.0 | ⛔️ |
|
| [napi_is_dataview](https://nodejs.org/api/n-api.html#n_api_napi_is_dataview) | 1 | v8.3.0 | ⛔️ |
|
||||||
|[napi_strict_equals](https://nodejs.org/api/n-api.html#n_api_napi_strict_equals)| 1 | v8.0.0 | ⛔️ |
|
| [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)| Experimental | v13.3.0 | ⛔️ |
|
| [napi_detach_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_detach_arraybuffer) | Experimental | v13.3.0 | ⛔️ |
|
||||||
|[napi_is_detached_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_is_detached_arraybuffer)| Experimental | v13.3.0 | ⛔️ |
|
| [napi_is_detached_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_is_detached_arraybuffer) | Experimental | v13.3.0 | ⛔️ |
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# napi-build
|
# napi-build
|
||||||
|
|
||||||
> Build support for napi-rs
|
> Build support for napi-rs
|
||||||
|
|
||||||
Setup `N-API` build in your `build.rs`:
|
Setup `N-API` build in your `build.rs`:
|
||||||
|
|
|
@ -8,10 +8,7 @@ use std::convert::TryInto;
|
||||||
|
|
||||||
register_module!(test_module, init);
|
register_module!(test_module, init);
|
||||||
|
|
||||||
fn init<'env>(
|
fn init(env: &Env, exports: &mut Value<Object>) -> Result<Option<Value<Object>>> {
|
||||||
env: &'env Env,
|
|
||||||
exports: &'env mut Value<'env, Object>,
|
|
||||||
) -> Result<Option<Value<'env, Object>>> {
|
|
||||||
exports.set_named_property("testThrow", env.create_function("testThrow", test_throw)?)?;
|
exports.set_named_property("testThrow", env.create_function("testThrow", test_throw)?)?;
|
||||||
|
|
||||||
exports.set_named_property("fibonacci", env.create_function("fibonacci", fibonacci)?)?;
|
exports.set_named_property("fibonacci", env.create_function("fibonacci", fibonacci)?)?;
|
||||||
|
@ -20,7 +17,7 @@ fn init<'env>(
|
||||||
|
|
||||||
#[js_function]
|
#[js_function]
|
||||||
fn test_throw(_ctx: CallContext) -> Result<Value<Any>> {
|
fn test_throw(_ctx: CallContext) -> Result<Value<Any>> {
|
||||||
Err(Error::new(Status::GenericFailure))
|
Err(Error::from_status(Status::GenericFailure))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[js_function(1)]
|
#[js_function(1)]
|
||||||
|
|
|
@ -102,16 +102,13 @@ pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
let env = Env::from_raw(raw_env);
|
let env = Env::from_raw(raw_env);
|
||||||
let call_ctx = CallContext::new(&env, raw_this, raw_args, #arg_len_span);
|
let call_ctx = CallContext::new(env, raw_this, raw_args, #arg_len_span);
|
||||||
let result = call_ctx.and_then(|ctx| #new_fn_name(ctx));
|
let result = call_ctx.and_then(|ctx| #new_fn_name(ctx));
|
||||||
has_error = has_error && result.is_err();
|
has_error = has_error && result.is_err();
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(result) => result.into_raw(),
|
Ok(result) => result.into_raw(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if !cfg!(windows) {
|
|
||||||
let _ = writeln!(::std::io::stderr(), "Error calling function: {:?}", e);
|
|
||||||
}
|
|
||||||
let message = format!("{:?}", e);
|
let message = format!("{:?}", e);
|
||||||
unsafe {
|
unsafe {
|
||||||
napi_rs::sys::napi_throw_error(raw_env, ptr::null(), message.as_ptr() as *const c_char);
|
napi_rs::sys::napi_throw_error(raw_env, ptr::null(), message.as_ptr() as *const c_char);
|
||||||
|
|
|
@ -7,6 +7,7 @@ description = "N-API bindings"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/Brooooooklyn/napi-rs"
|
repository = "https://github.com/Brooooooklyn/napi-rs"
|
||||||
keywords = ["NodeJS", "FFI", "NAPI", "n-api"]
|
keywords = ["NodeJS", "FFI", "NAPI", "n-api"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = { version = "0.3", features = ["default", "thread-pool"] }
|
futures = { version = "0.3", features = ["default", "thread-pool"] }
|
||||||
|
@ -25,7 +26,6 @@ tar = "0.4"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.53"
|
bindgen = "0.53"
|
||||||
cc = "1.0"
|
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
napi-build = { version = "0.1", path = "../build" }
|
napi-build = { version = "0.1", path = "../build" }
|
||||||
regex = "1.3"
|
regex = "1.3"
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
extern crate bindgen;
|
extern crate bindgen;
|
||||||
extern crate cc;
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
extern crate flate2;
|
extern crate flate2;
|
||||||
extern crate glob;
|
extern crate glob;
|
||||||
|
@ -36,8 +35,6 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
env::set_var("CARGO_RUSTC_FLAGS", "-Clink-args=-export_dynamic");
|
|
||||||
|
|
||||||
if node_major_version < 10 {
|
if node_major_version < 10 {
|
||||||
panic!("node version is too low")
|
panic!("node version is too low")
|
||||||
}
|
}
|
||||||
|
@ -60,31 +57,6 @@ fn main() {
|
||||||
.expect("Unable to generate napi bindings")
|
.expect("Unable to generate napi bindings")
|
||||||
.write_to_file(out_path.join("bindings.rs"))
|
.write_to_file(out_path.join("bindings.rs"))
|
||||||
.expect("Unable to write napi bindings");
|
.expect("Unable to write napi bindings");
|
||||||
|
|
||||||
let mut bindings_path = PathBuf::from("src");
|
|
||||||
bindings_path.push("sys");
|
|
||||||
bindings_path.push("bindings.cc");
|
|
||||||
|
|
||||||
let mut cc_builder = cc::Build::new();
|
|
||||||
|
|
||||||
cc_builder
|
|
||||||
.cpp(true)
|
|
||||||
.include(&node_include_path)
|
|
||||||
.file(bindings_path);
|
|
||||||
if !cfg!(windows) {
|
|
||||||
cc_builder.flag("-Wno-unused-parameter");
|
|
||||||
};
|
|
||||||
|
|
||||||
if cfg!(target_os = "macos") {
|
|
||||||
cc_builder.flag("-std=c++0x");
|
|
||||||
} else if cfg!(linux) || cfg!(target_env = "gnu") {
|
|
||||||
cc_builder.flag("-std=c++14");
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_builder
|
|
||||||
.cargo_metadata(true)
|
|
||||||
.out_dir(&out_path)
|
|
||||||
.compile("napi-bindings");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
|
|
@ -1,32 +1,35 @@
|
||||||
use crate::{sys, Any, Env, Error, Result, Status, Value, ValueType};
|
use crate::{sys, Any, Env, Error, Result, Status, Value, ValueType};
|
||||||
|
|
||||||
pub struct CallContext<'env, T: ValueType = Any> {
|
pub struct CallContext<T: ValueType = Any> {
|
||||||
pub env: &'env Env,
|
pub env: Env,
|
||||||
pub this: Value<'env, T>,
|
pub this: Value<T>,
|
||||||
args: [sys::napi_value; 8],
|
args: [sys::napi_value; 8],
|
||||||
arg_len: usize,
|
arg_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env, T: ValueType> CallContext<'env, T> {
|
impl<T: ValueType> CallContext<T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
env: &'env Env,
|
env: Env,
|
||||||
this: sys::napi_value,
|
this: sys::napi_value,
|
||||||
args: [sys::napi_value; 8],
|
args: [sys::napi_value; 8],
|
||||||
arg_len: usize,
|
arg_len: usize,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
env,
|
env,
|
||||||
this: Value::<'env, T>::from_raw(env, this)?,
|
this: Value::<T>::from_raw(env.0, this)?,
|
||||||
args,
|
args,
|
||||||
arg_len,
|
arg_len,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<ArgType: ValueType>(&'env self, index: usize) -> Result<Value<'env, ArgType>> {
|
pub fn get<ArgType: ValueType>(&self, index: usize) -> Result<Value<ArgType>> {
|
||||||
if index + 1 > self.arg_len {
|
if index + 1 > self.arg_len {
|
||||||
Err(Error::new(Status::GenericFailure))
|
Err(Error {
|
||||||
|
status: Status::GenericFailure,
|
||||||
|
reason: Some("Arguments index out of range".to_owned()),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Value::<'env, ArgType>::from_raw(&self.env, self.args[index])
|
Value::<ArgType>::from_raw(self.env.0, self.args[index])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use super::sys;
|
|
||||||
use futures::task::Poll;
|
use futures::task::Poll;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -7,16 +6,7 @@ use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::task::{Context, RawWaker, RawWakerVTable, Waker};
|
use std::task::{Context, RawWaker, RawWakerVTable, Waker};
|
||||||
|
|
||||||
pub struct LibuvExecutor {
|
use crate::{sys, Error, Result, Status};
|
||||||
event_loop: *mut sys::uv_loop_s,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
struct LibuvWaker(*mut sys::uv_async_t);
|
|
||||||
|
|
||||||
unsafe impl Send for LibuvWaker {}
|
|
||||||
|
|
||||||
unsafe impl Sync for LibuvWaker {}
|
|
||||||
|
|
||||||
const UV_ASYNC_V_TABLE: RawWakerVTable = RawWakerVTable::new(
|
const UV_ASYNC_V_TABLE: RawWakerVTable = RawWakerVTable::new(
|
||||||
clone_executor,
|
clone_executor,
|
||||||
|
@ -39,27 +29,28 @@ unsafe fn wake_uv_async_by_ref(uv_async_t: *const ()) {
|
||||||
assert!(status == 0, "wake_uv_async_by_ref failed");
|
assert!(status == 0, "wake_uv_async_by_ref failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn drop_uv_async(uv_async_t_ptr: *const ()) {
|
unsafe fn drop_uv_async(_uv_async_t_ptr: *const ()) {}
|
||||||
sys::uv_unref(uv_async_t_ptr as *mut sys::uv_handle_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Task<'a> {
|
struct Task<'a> {
|
||||||
future: Pin<Box<dyn Future<Output = ()>>>,
|
future: Pin<Box<dyn Future<Output = ()>>>,
|
||||||
context: Context<'a>,
|
context: Context<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LibuvExecutor {
|
pub fn execute<F: 'static + Future<Output = ()>>(
|
||||||
pub fn new(event_loop: *mut sys::uv_loop_s) -> Self {
|
event_loop: *mut sys::uv_loop_s,
|
||||||
Self { event_loop }
|
future: F,
|
||||||
}
|
) -> Result<()> {
|
||||||
|
|
||||||
pub fn execute<F: 'static + Future<Output = ()>>(&self, future: F) {
|
|
||||||
let uninit = mem::MaybeUninit::<sys::uv_async_t>::uninit();
|
let uninit = mem::MaybeUninit::<sys::uv_async_t>::uninit();
|
||||||
let uv_async_t: Box<sys::uv_async_t> = unsafe { Box::new(uninit.assume_init()) };
|
let uv_async_t: Box<sys::uv_async_t> = unsafe { Box::new(uninit.assume_init()) };
|
||||||
let uv_async_t_ref = Box::leak(uv_async_t);
|
let uv_async_t_ref = Box::leak(uv_async_t);
|
||||||
unsafe {
|
unsafe {
|
||||||
let status = sys::uv_async_init(self.event_loop, uv_async_t_ref, Some(poll_future));
|
let status = sys::uv_async_init(event_loop, uv_async_t_ref, Some(poll_future));
|
||||||
assert!(status == 0, "Non-zero status returned from uv_async_init");
|
if status != 0 {
|
||||||
|
return Err(Error {
|
||||||
|
status: Status::Unknown,
|
||||||
|
reason: Some("Non-zero status returned from uv_async_init".to_owned()),
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let waker = Waker::from_raw(RawWaker::new(
|
let waker = Waker::from_raw(RawWaker::new(
|
||||||
|
@ -77,8 +68,8 @@ impl LibuvExecutor {
|
||||||
uv_async_t_ref as *mut _ as *mut sys::uv_handle_t,
|
uv_async_t_ref as *mut _ as *mut sys::uv_handle_t,
|
||||||
Arc::into_raw(arc_task) as *mut c_void,
|
Arc::into_raw(arc_task) as *mut c_void,
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,10 +87,7 @@ unsafe extern "C" fn poll_future(handle: *mut sys::uv_async_t) {
|
||||||
let mut task = Arc::from_raw(data_ptr);
|
let mut task = Arc::from_raw(data_ptr);
|
||||||
if let Some(mut_task) = Arc::get_mut(&mut task) {
|
if let Some(mut_task) = Arc::get_mut(&mut task) {
|
||||||
if mut_task.poll_future() {
|
if mut_task.poll_future() {
|
||||||
sys::uv_close(
|
sys::uv_close(handle as *mut sys::uv_handle_t, None);
|
||||||
handle as *mut sys::uv_handle_t,
|
|
||||||
Some(drop_handle_after_close),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
Arc::into_raw(task);
|
Arc::into_raw(task);
|
||||||
};
|
};
|
||||||
|
@ -107,7 +95,3 @@ unsafe extern "C" fn poll_future(handle: *mut sys::uv_async_t) {
|
||||||
Arc::into_raw(task);
|
Arc::into_raw(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn drop_handle_after_close(handle: *mut sys::uv_handle_t) {
|
|
||||||
Box::from_raw(handle);
|
|
||||||
}
|
|
||||||
|
|
380
napi/src/lib.rs
380
napi/src/lib.rs
|
@ -1,5 +1,7 @@
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
|
|
||||||
|
use core::fmt::Debug;
|
||||||
|
use futures::prelude::*;
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
@ -14,17 +16,21 @@ use std::string::String as RustString;
|
||||||
|
|
||||||
mod call_context;
|
mod call_context;
|
||||||
mod executor;
|
mod executor;
|
||||||
|
mod promise;
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
|
mod version;
|
||||||
|
|
||||||
pub use call_context::CallContext;
|
pub use call_context::CallContext;
|
||||||
pub use sys::{napi_valuetype, Status};
|
pub use sys::{napi_valuetype, Status};
|
||||||
|
pub use version::NodeVersion;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
pub type Callback = extern "C" fn(sys::napi_env, sys::napi_callback_info) -> sys::napi_value;
|
pub type Callback = extern "C" fn(sys::napi_env, sys::napi_callback_info) -> sys::napi_value;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
status: Status,
|
pub status: Status,
|
||||||
|
pub reason: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
@ -75,8 +81,8 @@ pub struct ArrayBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Value<'env, T> {
|
pub struct Value<T> {
|
||||||
env: &'env Env,
|
env: sys::napi_env,
|
||||||
raw_value: sys::napi_value,
|
raw_value: sys::napi_value,
|
||||||
value: T,
|
value: T,
|
||||||
}
|
}
|
||||||
|
@ -87,14 +93,6 @@ pub struct Ref<T> {
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsyncContext {
|
|
||||||
raw_env: sys::napi_env,
|
|
||||||
raw_context: sys::napi_async_context,
|
|
||||||
raw_resource: sys::napi_ref,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Deferred(sys::napi_deferred);
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Property {
|
pub struct Property {
|
||||||
name: RustString,
|
name: RustString,
|
||||||
|
@ -141,7 +139,7 @@ macro_rules! register_module {
|
||||||
raw_exports: sys::napi_value,
|
raw_exports: sys::napi_value,
|
||||||
) -> sys::napi_value {
|
) -> sys::napi_value {
|
||||||
let env = Env::from_raw(raw_env);
|
let env = Env::from_raw(raw_env);
|
||||||
let mut exports: Value<Object> = Value::from_raw(&env, raw_exports).unwrap();
|
let mut exports: Value<Object> = Value::from_raw(raw_env, raw_exports).unwrap();
|
||||||
|
|
||||||
let result = $init(&env, &mut exports);
|
let result = $init(&env, &mut exports);
|
||||||
|
|
||||||
|
@ -162,15 +160,19 @@ macro_rules! register_module {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub fn new(status: Status) -> Self {
|
pub fn from_status(status: Status) -> Self {
|
||||||
Error { status: status }
|
Error {
|
||||||
|
status: status,
|
||||||
|
reason: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<std::ffi::NulError> for Error {
|
impl From<std::ffi::NulError> for Error {
|
||||||
fn from(_error: std::ffi::NulError) -> Self {
|
fn from(error: std::ffi::NulError) -> Self {
|
||||||
Error {
|
Error {
|
||||||
status: Status::StringExpected,
|
status: Status::StringExpected,
|
||||||
|
reason: Some(format!("{:?}", error)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,14 +182,14 @@ impl Env {
|
||||||
Env(env)
|
Env(env)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_undefined<'a>(&'a self) -> Result<Value<'a, Undefined>> {
|
pub fn get_undefined(&self) -> Result<Value<Undefined>> {
|
||||||
let mut raw_value = ptr::null_mut();
|
let mut raw_value = ptr::null_mut();
|
||||||
let status = unsafe { sys::napi_get_undefined(self.0, &mut raw_value) };
|
let status = unsafe { sys::napi_get_undefined(self.0, &mut raw_value) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
Ok(Value::from_raw_value(self, raw_value, Undefined))
|
Ok(Value::from_raw_value(self, raw_value, Undefined))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_null<'a>(&'a self) -> Result<Value<'a, Null>> {
|
pub fn get_null(&self) -> Result<Value<Null>> {
|
||||||
let mut raw_value = ptr::null_mut();
|
let mut raw_value = ptr::null_mut();
|
||||||
let status = unsafe { sys::napi_get_null(self.0, &mut raw_value) };
|
let status = unsafe { sys::napi_get_null(self.0, &mut raw_value) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
|
@ -201,7 +203,7 @@ impl Env {
|
||||||
Ok(Value::from_raw_value(self, raw_value, Boolean { value }))
|
Ok(Value::from_raw_value(self, raw_value, Boolean { value }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_int32<'a>(&'a self, int: i32) -> Result<Value<'a, Number>> {
|
pub fn create_int32(&self, int: i32) -> Result<Value<Number>> {
|
||||||
let mut raw_value = ptr::null_mut();
|
let mut raw_value = ptr::null_mut();
|
||||||
let status =
|
let status =
|
||||||
unsafe { sys::napi_create_int32(self.0, int, (&mut raw_value) as *mut sys::napi_value) };
|
unsafe { sys::napi_create_int32(self.0, int, (&mut raw_value) as *mut sys::napi_value) };
|
||||||
|
@ -209,7 +211,7 @@ impl Env {
|
||||||
Ok(Value::from_raw_value(self, raw_value, Number::Int32(int)))
|
Ok(Value::from_raw_value(self, raw_value, Number::Int32(int)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_int64<'a>(&'a self, int: i64) -> Result<Value<'a, Number>> {
|
pub fn create_int64(&self, int: i64) -> Result<Value<Number>> {
|
||||||
let mut raw_value = ptr::null_mut();
|
let mut raw_value = ptr::null_mut();
|
||||||
let status =
|
let status =
|
||||||
unsafe { sys::napi_create_int64(self.0, int, (&mut raw_value) as *mut sys::napi_value) };
|
unsafe { sys::napi_create_int64(self.0, int, (&mut raw_value) as *mut sys::napi_value) };
|
||||||
|
@ -217,7 +219,7 @@ impl Env {
|
||||||
Ok(Value::from_raw_value(self, raw_value, Number::Int(int)))
|
Ok(Value::from_raw_value(self, raw_value, Number::Int(int)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_uint32<'a>(&'a self, number: u32) -> Result<Value<'a, Number>> {
|
pub fn create_uint32(&self, number: u32) -> Result<Value<Number>> {
|
||||||
let mut raw_value = ptr::null_mut();
|
let mut raw_value = ptr::null_mut();
|
||||||
let status =
|
let status =
|
||||||
unsafe { sys::napi_create_uint32(self.0, number, (&mut raw_value) as *mut sys::napi_value) };
|
unsafe { sys::napi_create_uint32(self.0, number, (&mut raw_value) as *mut sys::napi_value) };
|
||||||
|
@ -225,7 +227,7 @@ impl Env {
|
||||||
Ok(Value::from_raw_value(self, raw_value, Number::U32(number)))
|
Ok(Value::from_raw_value(self, raw_value, Number::U32(number)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_double<'a>(&'a self, double: f64) -> Result<Value<'a, Number>> {
|
pub fn create_double(&self, double: f64) -> Result<Value<Number>> {
|
||||||
let mut raw_value = ptr::null_mut();
|
let mut raw_value = ptr::null_mut();
|
||||||
let status =
|
let status =
|
||||||
unsafe { sys::napi_create_double(self.0, double, (&mut raw_value) as *mut sys::napi_value) };
|
unsafe { sys::napi_create_double(self.0, double, (&mut raw_value) as *mut sys::napi_value) };
|
||||||
|
@ -237,7 +239,7 @@ impl Env {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_string<'a, 'b>(&'a self, s: &'b str) -> Result<Value<'a, JsString>> {
|
pub fn create_string<'a, 'b>(&'a self, s: &'b str) -> Result<Value<JsString>> {
|
||||||
let mut raw_value = ptr::null_mut();
|
let mut raw_value = ptr::null_mut();
|
||||||
let status = unsafe {
|
let status = unsafe {
|
||||||
sys::napi_create_string_utf8(
|
sys::napi_create_string_utf8(
|
||||||
|
@ -260,7 +262,7 @@ impl Env {
|
||||||
Ok(Value::from_raw_value(self, raw_value, JsString))
|
Ok(Value::from_raw_value(self, raw_value, JsString))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_object<'a>(&'a self) -> Result<Value<'a, Object>> {
|
pub fn create_object(&self) -> Result<Value<Object>> {
|
||||||
let mut raw_value = ptr::null_mut();
|
let mut raw_value = ptr::null_mut();
|
||||||
let status = unsafe { sys::napi_create_object(self.0, &mut raw_value) };
|
let status = unsafe { sys::napi_create_object(self.0, &mut raw_value) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
|
@ -365,11 +367,7 @@ impl Env {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_function<'a, 'b>(
|
pub fn create_function(&self, name: &str, callback: Callback) -> Result<Value<Function>> {
|
||||||
&'a self,
|
|
||||||
name: &'b str,
|
|
||||||
callback: Callback,
|
|
||||||
) -> Result<Value<'a, Function>> {
|
|
||||||
let mut raw_result = ptr::null_mut();
|
let mut raw_result = ptr::null_mut();
|
||||||
let status = unsafe {
|
let status = unsafe {
|
||||||
sys::napi_create_function(
|
sys::napi_create_function(
|
||||||
|
@ -414,7 +412,7 @@ impl Env {
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
Value::from_raw(self, raw_value)
|
Value::from_raw(self.0, raw_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define_class<'a, 'b>(
|
pub fn define_class<'a, 'b>(
|
||||||
|
@ -422,7 +420,7 @@ impl Env {
|
||||||
name: &'b str,
|
name: &'b str,
|
||||||
constructor_cb: Callback,
|
constructor_cb: Callback,
|
||||||
properties: Vec<Property>,
|
properties: Vec<Property>,
|
||||||
) -> Result<Value<'a, Function>> {
|
) -> Result<Value<Function>> {
|
||||||
let mut raw_result = ptr::null_mut();
|
let mut raw_result = ptr::null_mut();
|
||||||
let raw_properties = properties
|
let raw_properties = properties
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -473,10 +471,14 @@ impl Env {
|
||||||
let tagged_object: *mut TaggedObject<T> = mem::transmute(unknown_tagged_object);
|
let tagged_object: *mut TaggedObject<T> = mem::transmute(unknown_tagged_object);
|
||||||
(*tagged_object).object.as_mut().ok_or(Error {
|
(*tagged_object).object.as_mut().ok_or(Error {
|
||||||
status: Status::InvalidArg,
|
status: Status::InvalidArg,
|
||||||
|
reason: Some("Invalid argument, nothing attach to js_object".to_owned()),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(Error {
|
Err(Error {
|
||||||
status: Status::InvalidArg,
|
status: Status::InvalidArg,
|
||||||
|
reason: Some(
|
||||||
|
"Invalid argument, T on unrwap is not the type of wrapped object".to_owned(),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -496,35 +498,40 @@ impl Env {
|
||||||
} else {
|
} else {
|
||||||
Err(Error {
|
Err(Error {
|
||||||
status: Status::InvalidArg,
|
status: Status::InvalidArg,
|
||||||
|
reason: Some(
|
||||||
|
"Invalid argument, T on drop_wrapped is not the type of wrapped object".to_owned(),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn async_init(&self, resource: Option<Value<Object>>, name: &str) -> Result<AsyncContext> {
|
pub fn create_error(&self, e: Error) -> Result<Value<Object>> {
|
||||||
let raw_resource = resource
|
let reason = e.reason.unwrap_or("".to_owned());
|
||||||
.map(|r| Ok(r.into_raw()))
|
let reason_string = self.create_string(reason.as_str())?;
|
||||||
.unwrap_or_else(|| self.create_object().map(|o| o.into_raw()))?;
|
let mut result = ptr::null_mut();
|
||||||
let raw_name = self.create_string(name)?.into_raw();
|
let status = unsafe {
|
||||||
|
sys::napi_create_error(
|
||||||
let mut raw_context = ptr::null_mut();
|
self.0,
|
||||||
let mut raw_resource_ref = ptr::null_mut();
|
ptr::null_mut(),
|
||||||
unsafe {
|
reason_string.into_raw(),
|
||||||
let status = sys::napi_async_init(self.0, raw_resource, raw_name, &mut raw_context);
|
&mut result,
|
||||||
check_status(status)?;
|
)
|
||||||
|
};
|
||||||
let status = sys::napi_create_reference(self.0, raw_resource, 1, &mut raw_resource_ref);
|
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
|
Ok(Value::from_raw_value(self, result, Object))
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(AsyncContext {
|
pub fn perform_async_operation<
|
||||||
raw_env: self.0,
|
T: 'static,
|
||||||
raw_resource: raw_resource_ref,
|
V: 'static + ValueType,
|
||||||
raw_context,
|
F: 'static + Future<Output = Result<T>>,
|
||||||
})
|
R: 'static + FnOnce(&mut Env, T) -> Result<Value<V>>,
|
||||||
}
|
>(
|
||||||
|
&self,
|
||||||
pub fn create_promise(&self) -> Result<(Value<Object>, Deferred)> {
|
deferred: F,
|
||||||
|
resolver: R,
|
||||||
|
) -> Result<Value<Object>> {
|
||||||
let mut raw_promise = ptr::null_mut();
|
let mut raw_promise = ptr::null_mut();
|
||||||
let mut raw_deferred = ptr::null_mut();
|
let mut raw_deferred = ptr::null_mut();
|
||||||
|
|
||||||
|
@ -533,28 +540,41 @@ impl Env {
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((
|
|
||||||
Value::from_raw_value(self, raw_promise, Object),
|
|
||||||
Deferred(raw_deferred),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_deferred<T: ValueType>(&self, deferred: Deferred, value: Value<T>) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
let status = sys::napi_resolve_deferred(self.0, deferred.0, value.into_raw());
|
|
||||||
check_status(status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_executor(&self) -> executor::LibuvExecutor {
|
|
||||||
let event_loop = unsafe { sys::uv_default_loop() };
|
let event_loop = unsafe { sys::uv_default_loop() };
|
||||||
executor::LibuvExecutor::new(event_loop)
|
let raw_env = self.0;
|
||||||
|
executor::execute(
|
||||||
|
event_loop,
|
||||||
|
promise::resolve(self.0, deferred, resolver, raw_deferred).map(move |v| match v {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(e) => {
|
||||||
|
let cloned_error = e.clone();
|
||||||
|
unsafe {
|
||||||
|
sys::napi_throw_error(
|
||||||
|
raw_env,
|
||||||
|
ptr::null(),
|
||||||
|
e.reason.unwrap_or(format!("{:?}", e.status)).as_ptr() as *const _,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
eprintln!("{:?}", &cloned_error);
|
||||||
|
panic!(cloned_error);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(Value::from_raw_value(self, raw_promise, Object))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_node_version(&self) -> Result<NodeVersion> {
|
||||||
|
let mut result = ptr::null();
|
||||||
|
check_status(unsafe { sys::napi_get_node_version(self.0, &mut result) })?;
|
||||||
|
let version = unsafe { *result };
|
||||||
|
version.try_into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ValueType: Copy {
|
pub trait ValueType: Copy + Debug {
|
||||||
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result<Self>;
|
fn from_raw(env: sys::napi_env, raw: sys::napi_value) -> Result<Self>;
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool;
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValueType for Any {
|
impl ValueType for Any {
|
||||||
|
@ -562,8 +582,8 @@ impl ValueType for Any {
|
||||||
Ok(Any)
|
Ok(Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(_env: sys::napi_env, _raw: sys::napi_value) -> bool {
|
fn matches_raw_type(_env: sys::napi_env, _raw: sys::napi_value) -> Result<bool> {
|
||||||
true
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,8 +592,8 @@ impl ValueType for Undefined {
|
||||||
Ok(Undefined)
|
Ok(Undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_undefined
|
Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_undefined)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,8 +602,8 @@ impl ValueType for Null {
|
||||||
Ok(Null)
|
Ok(Null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_null
|
Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,8 +615,8 @@ impl ValueType for Boolean {
|
||||||
Ok(Boolean { value })
|
Ok(Boolean { value })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_boolean
|
Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_boolean)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,8 +628,8 @@ impl ValueType for Number {
|
||||||
Ok(Number::Double(double))
|
Ok(Number::Double(double))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_number
|
Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,8 +638,8 @@ impl ValueType for JsString {
|
||||||
Ok(JsString {})
|
Ok(JsString {})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_string
|
Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,8 +648,8 @@ impl ValueType for Object {
|
||||||
Ok(Object {})
|
Ok(Object {})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_object
|
Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,13 +665,13 @@ impl ValueType for Buffer {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
let mut result = false;
|
let mut result = false;
|
||||||
unsafe {
|
unsafe {
|
||||||
let status = sys::napi_is_buffer(env, raw, &mut result);
|
let status = sys::napi_is_buffer(env, raw, &mut result);
|
||||||
debug_assert!(Status::from(status) == Status::Ok);
|
check_status(status)?;
|
||||||
}
|
}
|
||||||
result
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,21 +687,21 @@ impl ValueType for ArrayBuffer {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
let mut result = false;
|
let mut result = false;
|
||||||
unsafe {
|
unsafe {
|
||||||
let status = sys::napi_is_arraybuffer(env, raw, &mut result);
|
let status = sys::napi_is_arraybuffer(env, raw, &mut result);
|
||||||
debug_assert!(Status::from(status) == Status::Ok);
|
check_status(status)?;
|
||||||
}
|
}
|
||||||
result
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Value<'env, Buffer> {
|
impl Value<Buffer> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_value(env: &'env Env, value: &Value<'env, Any>) -> Result<Value<'env, Buffer>> {
|
pub fn from_value(env: &Env, value: &Value<Any>) -> Result<Value<Buffer>> {
|
||||||
Ok(Value {
|
Ok(Value {
|
||||||
env,
|
env: env.0,
|
||||||
raw_value: value.raw_value,
|
raw_value: value.raw_value,
|
||||||
value: Buffer::from_raw(env.0, value.into_raw())?,
|
value: Buffer::from_raw(env.0, value.into_raw())?,
|
||||||
})
|
})
|
||||||
|
@ -693,25 +713,25 @@ impl ValueType for Function {
|
||||||
Ok(Function {})
|
Ok(Function {})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> bool {
|
fn matches_raw_type(env: sys::napi_env, raw: sys::napi_value) -> Result<bool> {
|
||||||
get_raw_type(env, raw) == sys::napi_valuetype::napi_function
|
Ok(get_raw_type(env, raw)? == sys::napi_valuetype::napi_function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env, T: ValueType> Value<'env, T> {
|
impl<T: ValueType> Value<T> {
|
||||||
pub fn from_raw_value(env: &'env Env, raw_value: sys::napi_value, value: T) -> Self {
|
pub fn from_raw_value(env: &Env, raw_value: sys::napi_value, value: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
env,
|
env: env.0,
|
||||||
raw_value,
|
raw_value,
|
||||||
value,
|
value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_raw(env: &'env Env, raw_value: sys::napi_value) -> Result<Self> {
|
pub fn from_raw(env: sys::napi_env, raw_value: sys::napi_value) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
env,
|
env,
|
||||||
raw_value,
|
raw_value,
|
||||||
value: T::from_raw(env.0, raw_value)?,
|
value: T::from_raw(env, raw_value)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -719,22 +739,22 @@ impl<'env, T: ValueType> Value<'env, T> {
|
||||||
self.raw_value
|
self.raw_value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn coerce_to_number(self) -> Result<Value<'env, Number>> {
|
pub fn coerce_to_number(self) -> Result<Value<Number>> {
|
||||||
let mut new_raw_value = ptr::null_mut();
|
let mut new_raw_value = ptr::null_mut();
|
||||||
let status =
|
let status =
|
||||||
unsafe { sys::napi_coerce_to_number(self.env.0, self.raw_value, &mut new_raw_value) };
|
unsafe { sys::napi_coerce_to_number(self.env, self.raw_value, &mut new_raw_value) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
Ok(Value {
|
Ok(Value {
|
||||||
env: self.env,
|
env: self.env,
|
||||||
raw_value: self.raw_value,
|
raw_value: self.raw_value,
|
||||||
value: Number::from_raw(self.env.0, self.raw_value)?,
|
value: Number::from_raw(self.env, self.raw_value)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn coerce_to_string(self) -> Result<Value<'env, JsString>> {
|
pub fn coerce_to_string(self) -> Result<Value<JsString>> {
|
||||||
let mut new_raw_value = ptr::null_mut();
|
let mut new_raw_value = ptr::null_mut();
|
||||||
let status =
|
let status =
|
||||||
unsafe { sys::napi_coerce_to_string(self.env.0, self.raw_value, &mut new_raw_value) };
|
unsafe { sys::napi_coerce_to_string(self.env, self.raw_value, &mut new_raw_value) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
Ok(Value {
|
Ok(Value {
|
||||||
env: self.env,
|
env: self.env,
|
||||||
|
@ -743,11 +763,11 @@ impl<'env, T: ValueType> Value<'env, T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn coerce_to_object(self) -> Result<Value<'env, Object>> {
|
pub fn coerce_to_object(self) -> Result<Value<Object>> {
|
||||||
let mut new_raw_value = ptr::null_mut();
|
let mut new_raw_value = ptr::null_mut();
|
||||||
let status = unsafe {
|
let status = unsafe {
|
||||||
sys::napi_coerce_to_object(
|
sys::napi_coerce_to_object(
|
||||||
self.env.0,
|
self.env,
|
||||||
self.raw_value,
|
self.raw_value,
|
||||||
(&mut new_raw_value) as *mut sys::napi_value,
|
(&mut new_raw_value) as *mut sys::napi_value,
|
||||||
)
|
)
|
||||||
|
@ -761,7 +781,7 @@ impl<'env, T: ValueType> Value<'env, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_any(self) -> Value<'env, Any> {
|
pub fn into_any(self) -> Value<Any> {
|
||||||
Value {
|
Value {
|
||||||
env: self.env,
|
env: self.env,
|
||||||
raw_value: self.raw_value,
|
raw_value: self.raw_value,
|
||||||
|
@ -771,27 +791,26 @@ impl<'env, T: ValueType> Value<'env, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_raw_type(env: sys::napi_env, raw_value: sys::napi_value) -> sys::napi_valuetype {
|
fn get_raw_type(env: sys::napi_env, raw_value: sys::napi_value) -> Result<sys::napi_valuetype> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let value_type = ptr::null_mut();
|
let value_type = ptr::null_mut();
|
||||||
let status = sys::napi_typeof(env, raw_value, value_type);
|
check_status(sys::napi_typeof(env, raw_value, value_type))?;
|
||||||
debug_assert!(Status::from(status) == Status::Ok);
|
Ok(*value_type)
|
||||||
*value_type
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Value<'env, Boolean> {
|
impl Value<Boolean> {
|
||||||
pub fn get_value(&self) -> bool {
|
pub fn get_value(&self) -> bool {
|
||||||
self.value.value
|
self.value.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Value<'env, JsString> {
|
impl Value<JsString> {
|
||||||
pub fn len(&self) -> Result<usize> {
|
pub fn len(&self) -> Result<usize> {
|
||||||
let mut raw_length = ptr::null_mut();
|
let mut raw_length = ptr::null_mut();
|
||||||
unsafe {
|
unsafe {
|
||||||
let status = sys::napi_get_named_property(
|
let status = sys::napi_get_named_property(
|
||||||
self.env.0,
|
self.env,
|
||||||
self.raw_value,
|
self.raw_value,
|
||||||
"length\0".as_ptr() as *const c_char,
|
"length\0".as_ptr() as *const c_char,
|
||||||
&mut raw_length,
|
&mut raw_length,
|
||||||
|
@ -803,7 +822,7 @@ impl<'env> Value<'env, JsString> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Value<'env, JsString> {
|
impl Value<JsString> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_ref(&self) -> Result<&[u8]> {
|
pub fn get_ref(&self) -> Result<&[u8]> {
|
||||||
let mut written_char_count: u64 = 0;
|
let mut written_char_count: u64 = 0;
|
||||||
|
@ -811,7 +830,7 @@ impl<'env> Value<'env, JsString> {
|
||||||
let mut result = Vec::with_capacity(len);
|
let mut result = Vec::with_capacity(len);
|
||||||
unsafe {
|
unsafe {
|
||||||
let status = sys::napi_get_value_string_utf8(
|
let status = sys::napi_get_value_string_utf8(
|
||||||
self.env.0,
|
self.env,
|
||||||
self.raw_value,
|
self.raw_value,
|
||||||
result.as_mut_ptr(),
|
result.as_mut_ptr(),
|
||||||
len as u64,
|
len as u64,
|
||||||
|
@ -829,7 +848,10 @@ impl<'env> Value<'env, JsString> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_str(&self) -> Result<&str> {
|
pub fn as_str(&self) -> Result<&str> {
|
||||||
str::from_utf8(self.get_ref()?).map_err(|_| Error::new(Status::GenericFailure))
|
str::from_utf8(self.get_ref()?).map_err(|e| Error {
|
||||||
|
status: Status::GenericFailure,
|
||||||
|
reason: Some(format!("{:?}", e)),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ref_mut(&mut self) -> Result<&mut [u8]> {
|
pub fn get_ref_mut(&mut self) -> Result<&mut [u8]> {
|
||||||
|
@ -838,7 +860,7 @@ impl<'env> Value<'env, JsString> {
|
||||||
let mut result = Vec::with_capacity(len);
|
let mut result = Vec::with_capacity(len);
|
||||||
unsafe {
|
unsafe {
|
||||||
let status = sys::napi_get_value_string_utf8(
|
let status = sys::napi_get_value_string_utf8(
|
||||||
self.env.0,
|
self.env,
|
||||||
self.raw_value,
|
self.raw_value,
|
||||||
result.as_mut_ptr(),
|
result.as_mut_ptr(),
|
||||||
len as u64,
|
len as u64,
|
||||||
|
@ -856,16 +878,16 @@ impl<'env> Value<'env, JsString> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> TryFrom<Value<'env, JsString>> for Vec<u16> {
|
impl TryFrom<Value<JsString>> for Vec<u16> {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value<'env, JsString>) -> Result<Vec<u16>> {
|
fn try_from(value: Value<JsString>) -> Result<Vec<u16>> {
|
||||||
let mut result = Vec::with_capacity(value.len()? + 1); // Leave room for trailing null byte
|
let mut result = Vec::with_capacity(value.len()? + 1); // Leave room for trailing null byte
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut written_char_count = 0;
|
let mut written_char_count = 0;
|
||||||
let status = sys::napi_get_value_string_utf16(
|
let status = sys::napi_get_value_string_utf16(
|
||||||
value.env.0,
|
value.env,
|
||||||
value.raw_value,
|
value.raw_value,
|
||||||
result.as_mut_ptr(),
|
result.as_mut_ptr(),
|
||||||
result.capacity() as u64,
|
result.capacity() as u64,
|
||||||
|
@ -879,63 +901,63 @@ impl<'env> TryFrom<Value<'env, JsString>> for Vec<u16> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> TryFrom<Value<'env, Number>> for usize {
|
impl TryFrom<Value<Number>> for usize {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value<'env, Number>) -> Result<usize> {
|
fn try_from(value: Value<Number>) -> Result<usize> {
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
let status = unsafe { sys::napi_get_value_int64(value.env.0, value.raw_value, &mut result) };
|
let status = unsafe { sys::napi_get_value_int64(value.env, value.raw_value, &mut result) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
Ok(result as usize)
|
Ok(result as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> TryFrom<Value<'env, Number>> for u32 {
|
impl TryFrom<Value<Number>> for u32 {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value<'env, Number>) -> Result<u32> {
|
fn try_from(value: Value<Number>) -> Result<u32> {
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
let status = unsafe { sys::napi_get_value_uint32(value.env.0, value.raw_value, &mut result) };
|
let status = unsafe { sys::napi_get_value_uint32(value.env, value.raw_value, &mut result) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> TryFrom<Value<'env, Number>> for i32 {
|
impl TryFrom<Value<Number>> for i32 {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value<'env, Number>) -> Result<i32> {
|
fn try_from(value: Value<Number>) -> Result<i32> {
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
let status = unsafe { sys::napi_get_value_int32(value.env.0, value.raw_value, &mut result) };
|
let status = unsafe { sys::napi_get_value_int32(value.env, value.raw_value, &mut result) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> TryFrom<Value<'env, Number>> for i64 {
|
impl TryFrom<Value<Number>> for i64 {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value<'env, Number>) -> Result<i64> {
|
fn try_from(value: Value<Number>) -> Result<i64> {
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
let status = unsafe { sys::napi_get_value_int64(value.env.0, value.raw_value, &mut result) };
|
let status = unsafe { sys::napi_get_value_int64(value.env, value.raw_value, &mut result) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> TryFrom<Value<'env, Number>> for f64 {
|
impl TryFrom<Value<Number>> for f64 {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Value<'env, Number>) -> Result<f64> {
|
fn try_from(value: Value<Number>) -> Result<f64> {
|
||||||
let mut result = 0_f64;
|
let mut result = 0_f64;
|
||||||
let status = unsafe { sys::napi_get_value_double(value.env.0, value.raw_value, &mut result) };
|
let status = unsafe { sys::napi_get_value_double(value.env, value.raw_value, &mut result) };
|
||||||
check_status(status)?;
|
check_status(status)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Value<'env, Object> {
|
impl Value<Object> {
|
||||||
pub fn set_property<'a, K, V>(&mut self, key: Value<K>, value: Value<V>) -> Result<()> {
|
pub fn set_property<K, V>(&mut self, key: Value<K>, value: Value<V>) -> Result<()> {
|
||||||
let status = unsafe {
|
let status = unsafe {
|
||||||
sys::napi_set_property(
|
sys::napi_set_property(
|
||||||
self.raw_env(),
|
self.raw_env(),
|
||||||
|
@ -948,11 +970,7 @@ impl<'env> Value<'env, Object> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_named_property<'a, T, V: Into<Value<'a, T>>>(
|
pub fn set_named_property<T, V: Into<Value<T>>>(&mut self, name: &str, value: V) -> Result<()> {
|
||||||
&mut self,
|
|
||||||
name: &'a str,
|
|
||||||
value: V,
|
|
||||||
) -> Result<()> {
|
|
||||||
let key = CString::new(name)?;
|
let key = CString::new(name)?;
|
||||||
let status = unsafe {
|
let status = unsafe {
|
||||||
sys::napi_set_named_property(
|
sys::napi_set_named_property(
|
||||||
|
@ -990,7 +1008,7 @@ impl<'env> Value<'env, Object> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_index<'a, T>(&mut self, index: usize, value: Value<T>) -> Result<()> {
|
pub fn set_index<'a, T>(&mut self, index: usize, value: Value<T>) -> Result<()> {
|
||||||
self.set_property(self.env.create_int64(index as i64)?, value)
|
self.set_property(Env::from_raw(self.env).create_int64(index as i64)?, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_index<T: ValueType>(&self, index: u32) -> Result<Value<T>> {
|
pub fn get_index<T: ValueType>(&self, index: u32) -> Result<Value<T>> {
|
||||||
|
@ -1015,7 +1033,7 @@ impl<'env> Value<'env, Object> {
|
||||||
Ok(is_buffer)
|
Ok(is_buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_buffer(&self) -> Result<Value<'env, Buffer>> {
|
pub fn to_buffer(&self) -> Result<Value<Buffer>> {
|
||||||
Value::from_raw(self.env, self.raw_value)
|
Value::from_raw(self.env, self.raw_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,6 +1041,7 @@ impl<'env> Value<'env, Object> {
|
||||||
if self.is_array()? != true {
|
if self.is_array()? != true {
|
||||||
return Err(Error {
|
return Err(Error {
|
||||||
status: Status::ArrayExpected,
|
status: Status::ArrayExpected,
|
||||||
|
reason: Some("Object is not array".to_owned()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let mut length: u32 = 0;
|
let mut length: u32 = 0;
|
||||||
|
@ -1037,17 +1056,17 @@ impl<'env> Value<'env, Object> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raw_env(&self) -> sys::napi_env {
|
fn raw_env(&self) -> sys::napi_env {
|
||||||
self.env.0
|
self.env
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> AsRef<[u8]> for Value<'env, Buffer> {
|
impl AsRef<[u8]> for Value<Buffer> {
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] {
|
||||||
self.deref()
|
self.deref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Deref for Value<'env, Buffer> {
|
impl Deref for Value<Buffer> {
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
|
|
||||||
fn deref(&self) -> &[u8] {
|
fn deref(&self) -> &[u8] {
|
||||||
|
@ -1055,13 +1074,13 @@ impl<'env> Deref for Value<'env, Buffer> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> DerefMut for Value<'env, Buffer> {
|
impl DerefMut for Value<Buffer> {
|
||||||
fn deref_mut(&mut self) -> &mut [u8] {
|
fn deref_mut(&mut self) -> &mut [u8] {
|
||||||
unsafe { slice::from_raw_parts_mut(self.value.data as *mut _, self.value.size as usize) }
|
unsafe { slice::from_raw_parts_mut(self.value.data as *mut _, self.value.size as usize) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Deref for Value<'env, ArrayBuffer> {
|
impl Deref for Value<ArrayBuffer> {
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
|
|
||||||
fn deref(&self) -> &[u8] {
|
fn deref(&self) -> &[u8] {
|
||||||
|
@ -1069,22 +1088,26 @@ impl<'env> Deref for Value<'env, ArrayBuffer> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> DerefMut for Value<'env, ArrayBuffer> {
|
impl DerefMut for Value<ArrayBuffer> {
|
||||||
fn deref_mut(&mut self) -> &mut [u8] {
|
fn deref_mut(&mut self) -> &mut [u8] {
|
||||||
unsafe { slice::from_raw_parts_mut(self.value.data as *mut _, self.value.size as usize) }
|
unsafe { slice::from_raw_parts_mut(self.value.data as *mut _, self.value.size as usize) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Value<'env, Function> {
|
impl Value<Function> {
|
||||||
pub fn call(
|
pub fn call(&self, this: Option<&Value<Object>>, args: &[Value<Any>]) -> Result<Value<Any>> {
|
||||||
&self,
|
|
||||||
this: Option<&Value<'env, Object>>,
|
|
||||||
args: &[Value<'env, Any>],
|
|
||||||
) -> Result<Value<'env, Any>> {
|
|
||||||
let raw_this = this
|
let raw_this = this
|
||||||
.map(|v| v.into_raw())
|
.map(|v| v.into_raw())
|
||||||
.or_else(|| self.env.get_undefined().ok().map(|u| u.into_raw()))
|
.or_else(|| {
|
||||||
.ok_or(Error::new(Status::Unknown))?;
|
Env::from_raw(self.env)
|
||||||
|
.get_undefined()
|
||||||
|
.ok()
|
||||||
|
.map(|u| u.into_raw())
|
||||||
|
})
|
||||||
|
.ok_or(Error {
|
||||||
|
status: Status::Unknown,
|
||||||
|
reason: Some("Get raw this failed".to_owned()),
|
||||||
|
})?;
|
||||||
let mut raw_args = unsafe { mem::MaybeUninit::<[sys::napi_value; 8]>::uninit().assume_init() };
|
let mut raw_args = unsafe { mem::MaybeUninit::<[sys::napi_value; 8]>::uninit().assume_init() };
|
||||||
for (i, arg) in args.into_iter().enumerate() {
|
for (i, arg) in args.into_iter().enumerate() {
|
||||||
raw_args[i] = arg.raw_value;
|
raw_args[i] = arg.raw_value;
|
||||||
|
@ -1092,7 +1115,7 @@ impl<'env> Value<'env, Function> {
|
||||||
let mut return_value = ptr::null_mut();
|
let mut return_value = ptr::null_mut();
|
||||||
let status = unsafe {
|
let status = unsafe {
|
||||||
sys::napi_call_function(
|
sys::napi_call_function(
|
||||||
self.env.0,
|
self.env,
|
||||||
raw_this,
|
raw_this,
|
||||||
self.raw_value,
|
self.raw_value,
|
||||||
args.len() as u64,
|
args.len() as u64,
|
||||||
|
@ -1106,9 +1129,9 @@ impl<'env> Value<'env, Function> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> Value<'env, Any> {
|
impl Value<Any> {
|
||||||
pub fn get_type(&self) -> sys::napi_valuetype {
|
pub fn get_type(&self) -> Result<sys::napi_valuetype> {
|
||||||
get_raw_type(self.env.0, self.raw_value)
|
get_raw_type(self.env, self.raw_value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,34 +1150,6 @@ impl<T> Drop for Ref<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsyncContext {
|
|
||||||
pub fn enter<'a, F: 'a + FnOnce(&mut Env)>(&'a self, run_in_context: F) {
|
|
||||||
let mut env = Env::from_raw(self.raw_env);
|
|
||||||
let mut handle_scope = ptr::null_mut();
|
|
||||||
let mut callback_scope = ptr::null_mut();
|
|
||||||
let mut raw_resource = ptr::null_mut();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
sys::napi_open_handle_scope(env.0, &mut handle_scope);
|
|
||||||
sys::napi_get_reference_value(env.0, self.raw_resource, &mut raw_resource);
|
|
||||||
sys::extras_open_callback_scope(self.raw_context, raw_resource, &mut callback_scope);
|
|
||||||
}
|
|
||||||
run_in_context(&mut env);
|
|
||||||
unsafe {
|
|
||||||
sys::extras_close_callback_scope(callback_scope);
|
|
||||||
sys::napi_close_handle_scope(env.0, handle_scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for AsyncContext {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
sys::napi_delete_reference(self.raw_env, self.raw_resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Property {
|
impl Property {
|
||||||
pub fn new(name: &str) -> Self {
|
pub fn new(name: &str) -> Self {
|
||||||
Property {
|
Property {
|
||||||
|
@ -1202,11 +1197,12 @@ impl<T: 'static> TaggedObject<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn check_status(code: sys::napi_status) -> Result<()> {
|
fn check_status(code: sys::napi_status) -> Result<()> {
|
||||||
let status = Status::from(code);
|
let status = Status::from(code);
|
||||||
match status {
|
match status {
|
||||||
Status::Ok => Ok(()),
|
Status::Ok => Ok(()),
|
||||||
_ => Err(Error { status }),
|
_ => Err(Error::from_status(status)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
65
napi/src/promise.rs
Normal file
65
napi/src/promise.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use futures::prelude::*;
|
||||||
|
use std::os::raw::c_char;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
use crate::{check_status, sys, Env, Result, Value, ValueType};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub async fn resolve<
|
||||||
|
T,
|
||||||
|
V: ValueType,
|
||||||
|
R: FnOnce(&mut Env, T) -> Result<Value<V>>,
|
||||||
|
F: Future<Output = Result<T>>,
|
||||||
|
>(
|
||||||
|
env: sys::napi_env,
|
||||||
|
fut: F,
|
||||||
|
resolver: R,
|
||||||
|
raw_deferred: sys::napi_deferred,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut raw_resource = ptr::null_mut();
|
||||||
|
let status = unsafe { sys::napi_create_object(env, &mut raw_resource) };
|
||||||
|
check_status(status)?;
|
||||||
|
let mut raw_name = ptr::null_mut();
|
||||||
|
let s = "napi_async_context";
|
||||||
|
let status = unsafe {
|
||||||
|
sys::napi_create_string_utf8(
|
||||||
|
env,
|
||||||
|
s.as_ptr() as *const c_char,
|
||||||
|
s.len() as u64,
|
||||||
|
&mut raw_name,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
check_status(status)?;
|
||||||
|
let mut raw_context = ptr::null_mut();
|
||||||
|
unsafe {
|
||||||
|
let status = sys::napi_async_init(env, raw_resource, raw_name, &mut raw_context);
|
||||||
|
check_status(status)?;
|
||||||
|
}
|
||||||
|
let mut handle_scope = ptr::null_mut();
|
||||||
|
match fut.await {
|
||||||
|
Ok(v) => unsafe {
|
||||||
|
check_status(sys::napi_open_handle_scope(env, &mut handle_scope))?;
|
||||||
|
let mut tmp_env = Env::from_raw(env);
|
||||||
|
let js_value = resolver(&mut tmp_env, v)?;
|
||||||
|
check_status(sys::napi_resolve_deferred(
|
||||||
|
env,
|
||||||
|
raw_deferred,
|
||||||
|
js_value.raw_value,
|
||||||
|
))?;
|
||||||
|
check_status(sys::napi_close_handle_scope(env, handle_scope))?;
|
||||||
|
},
|
||||||
|
Err(e) => unsafe {
|
||||||
|
check_status(sys::napi_open_handle_scope(env, &mut handle_scope))?;
|
||||||
|
check_status(sys::napi_reject_deferred(
|
||||||
|
env,
|
||||||
|
raw_deferred,
|
||||||
|
Env::from_raw(env)
|
||||||
|
.create_error(e)
|
||||||
|
.map(|e| e.into_raw())
|
||||||
|
.unwrap_or(ptr::null_mut()),
|
||||||
|
))?;
|
||||||
|
check_status(sys::napi_close_handle_scope(env, handle_scope))?;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
#include "bindings.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <node.h>
|
|
||||||
#include <v8.h>
|
|
||||||
|
|
||||||
static v8::Local<v8::Value> V8LocalValueFromJsValue(napi_value v)
|
|
||||||
{
|
|
||||||
v8::Local<v8::Value> local;
|
|
||||||
memcpy(&local, &v, sizeof(v));
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERN_C_START
|
|
||||||
|
|
||||||
NAPI_EXTERN void extras_open_callback_scope(napi_async_context napi_async_context,
|
|
||||||
napi_value napi_resource_object,
|
|
||||||
extras_callback_scope *result)
|
|
||||||
{
|
|
||||||
v8::Isolate *isolate = v8::Isolate::GetCurrent();
|
|
||||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
|
||||||
v8::Local<v8::Object> resource_object = V8LocalValueFromJsValue(napi_resource_object)->ToObject(context).ToLocalChecked();
|
|
||||||
node::async_context *node_async_context = reinterpret_cast<node::async_context *>(napi_async_context);
|
|
||||||
*result = reinterpret_cast<extras_callback_scope>(new node::CallbackScope(isolate, resource_object, *node_async_context));
|
|
||||||
}
|
|
||||||
|
|
||||||
NAPI_EXTERN void extras_close_callback_scope(extras_callback_scope callback_scope)
|
|
||||||
{
|
|
||||||
delete reinterpret_cast<node::CallbackScope *>(callback_scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERN_C_END
|
|
|
@ -1,15 +1,2 @@
|
||||||
#include <node_api.h>
|
#include <node_api.h>
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
typedef struct extras_callback_scope__ *extras_callback_scope;
|
|
||||||
|
|
||||||
EXTERN_C_START
|
|
||||||
|
|
||||||
NAPI_EXTERN void extras_open_callback_scope(napi_async_context napi_async_context,
|
|
||||||
napi_value napi_resource_object,
|
|
||||||
extras_callback_scope *result);
|
|
||||||
|
|
||||||
NAPI_EXTERN void extras_close_callback_scope(extras_callback_scope callback_scope);
|
|
||||||
|
|
||||||
EXTERN_C_END
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::napi_status;
|
use super::napi_status;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Debug)]
|
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
Ok,
|
Ok,
|
||||||
InvalidArg,
|
InvalidArg,
|
||||||
|
|
29
napi/src/version.rs
Normal file
29
napi/src/version.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
use crate::{sys, Error, Status};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct NodeVersion {
|
||||||
|
pub major: u32,
|
||||||
|
pub minor: u32,
|
||||||
|
pub patch: u32,
|
||||||
|
pub release: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<sys::napi_node_version> for NodeVersion {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(value: sys::napi_node_version) -> Result<NodeVersion, Error> {
|
||||||
|
Ok(NodeVersion {
|
||||||
|
major: value.major,
|
||||||
|
minor: value.minor,
|
||||||
|
patch: value.patch,
|
||||||
|
release: unsafe {
|
||||||
|
CStr::from_ptr(value.release).to_str().map_err(|_| Error {
|
||||||
|
status: Status::StringExpected,
|
||||||
|
reason: Some("Invalid release name".to_owned()),
|
||||||
|
})?
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
26
package.json
26
package.json
|
@ -17,6 +17,13 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"format": "run-p format:md format:json format:yaml format:source",
|
||||||
|
"format:md": "prettier --parser markdown --write './**/*.md'",
|
||||||
|
"format:json": "prettier --parser json --write './**/*.json'",
|
||||||
|
"format:source": "prettier --config ./package.json --write './**/*.js'",
|
||||||
|
"format:yaml": "prettier --parser yaml --write './**/*.{yml,yaml}'"
|
||||||
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/Brooooooklyn/napi-rs/issues"
|
"url": "https://github.com/Brooooooklyn/napi-rs/issues"
|
||||||
},
|
},
|
||||||
|
@ -32,12 +39,23 @@
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
"arrowParens": "always"
|
"arrowParens": "always"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": ["scripts/napi.js", "LICENSE"],
|
||||||
"scripts/napi.js",
|
"lint-staged": {
|
||||||
"LICENSE"
|
"*.js": ["prettier --write"],
|
||||||
],
|
"*.@(yml|yaml)": ["prettier --parser yaml --write"],
|
||||||
|
"*.json": ["prettier --parser json --write"],
|
||||||
|
"*.md": ["prettier --parser markdown --write"]
|
||||||
|
},
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "lint-staged && cargo fmt --all"
|
||||||
|
}
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^13.13.5",
|
"@types/node": "^13.13.5",
|
||||||
|
"husky": "^4.2.5",
|
||||||
|
"lint-staged": "^10.2.2",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^2.0.5"
|
"prettier": "^2.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,10 @@ let tomlContent
|
||||||
let moduleName
|
let moduleName
|
||||||
|
|
||||||
try {
|
try {
|
||||||
tomlContentString = fs.readFileSync(path.join(process.cwd(), 'Cargo.toml'), 'utf-8')
|
tomlContentString = fs.readFileSync(
|
||||||
|
path.join(process.cwd(), 'Cargo.toml'),
|
||||||
|
'utf-8',
|
||||||
|
)
|
||||||
} catch {
|
} catch {
|
||||||
throw new TypeError('Can not find Cargo.toml in process.cwd')
|
throw new TypeError('Can not find Cargo.toml in process.cwd')
|
||||||
}
|
}
|
||||||
|
@ -60,7 +63,9 @@ const targetDir = argv.release ? 'release' : 'debug'
|
||||||
|
|
||||||
const platformName = argv.platform ? `.${platform}` : ''
|
const platformName = argv.platform ? `.${platform}` : ''
|
||||||
|
|
||||||
let subcommand = argv._[0] || path.join('target', targetDir, `${moduleName}${platformName}.node`)
|
let subcommand =
|
||||||
|
argv._[0] ||
|
||||||
|
path.join('target', targetDir, `${moduleName}${platformName}.node`)
|
||||||
const parsedDist = path.parse(subcommand)
|
const parsedDist = path.parse(subcommand)
|
||||||
|
|
||||||
if (!parsedDist.name || parsedDist.name === '.') {
|
if (!parsedDist.name || parsedDist.name === '.') {
|
||||||
|
@ -73,11 +78,13 @@ if (!parsedDist.ext) {
|
||||||
|
|
||||||
const pos = __dirname.indexOf('node_modules')
|
const pos = __dirname.indexOf('node_modules')
|
||||||
|
|
||||||
const dylibContent = fs.readFileSync(path.join(
|
const dylibContent = fs.readFileSync(
|
||||||
|
path.join(
|
||||||
__dirname.substring(0, pos),
|
__dirname.substring(0, pos),
|
||||||
'target',
|
'target',
|
||||||
targetDir,
|
targetDir,
|
||||||
`${dylibName}${libExt}`,
|
`${dylibName}${libExt}`,
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
fs.writeFileSync(subcommand, dylibContent)
|
fs.writeFileSync(subcommand, dylibContent)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const testModule = require(`./target/debug/test_module.node`)
|
const testModule = require('./index.node')
|
||||||
|
|
||||||
function testSpawn() {
|
function testSpawn() {
|
||||||
console.log('=== Test spawning a future on libuv event loop')
|
console.log('=== Test spawning a future on libuv event loop')
|
||||||
|
@ -9,19 +9,21 @@ function testThrow() {
|
||||||
console.log('=== Test throwing from Rust')
|
console.log('=== Test throwing from Rust')
|
||||||
try {
|
try {
|
||||||
testModule.testThrow()
|
testModule.testThrow()
|
||||||
} catch (e) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
console.error('Expected function to throw an error')
|
console.error('Expected function to throw an error')
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const future = testSpawn()
|
const future = testSpawn()
|
||||||
|
|
||||||
// https://github.com/nodejs/node/issues/29355
|
future
|
||||||
setTimeout(() => {
|
.then((value) => {
|
||||||
future.then(testThrow).catch((e) => {
|
console.info(`${value} from napi`)
|
||||||
|
testThrow()
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
}, 1000)
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
"name": "test-module",
|
"name": "test-module",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cargo build && node ../scripts/napi.js",
|
"build": "cargo build && node ../scripts/napi.js ./index",
|
||||||
"build-release": "cargo build --release && node ../scripts/napi.js --release",
|
"build-release": "cargo build --release && node ../scripts/napi.js --release ./index",
|
||||||
"test": "node ./index.js"
|
"test": "node ./index.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,49 +9,36 @@ use napi::{Any, CallContext, Env, Error, Object, Result, Status, Value};
|
||||||
|
|
||||||
register_module!(test_module, init);
|
register_module!(test_module, init);
|
||||||
|
|
||||||
fn init<'env>(
|
fn init(env: &Env, exports: &mut Value<Object>) -> Result<Option<Value<Object>>> {
|
||||||
env: &'env Env,
|
|
||||||
exports: &'env mut Value<'env, Object>,
|
|
||||||
) -> Result<Option<Value<'env, Object>>> {
|
|
||||||
exports.set_named_property("testSpawn", env.create_function("testSpawn", test_spawn)?)?;
|
exports.set_named_property("testSpawn", env.create_function("testSpawn", test_spawn)?)?;
|
||||||
exports.set_named_property("testThrow", env.create_function("testThrow", test_throw)?)?;
|
exports.set_named_property("testThrow", env.create_function("testThrow", test_throw)?)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[js_function]
|
#[js_function]
|
||||||
fn test_spawn<'a>(ctx: CallContext<'a>) -> Result<Value<'a, Object>> {
|
fn test_spawn(ctx: CallContext) -> Result<Value<Object>> {
|
||||||
use futures::executor::ThreadPool;
|
use futures::executor::ThreadPool;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
let env = ctx.env;
|
let env = ctx.env;
|
||||||
let async_context = env.async_init(None, "test_spawn")?;
|
|
||||||
let pool = ThreadPool::new().expect("Failed to build pool");
|
let pool = ThreadPool::new().expect("Failed to build pool");
|
||||||
let (promise, deferred) = env.create_promise()?;
|
|
||||||
let (tx, rx) = futures::channel::mpsc::unbounded::<i32>();
|
let (tx, rx) = futures::channel::mpsc::unbounded::<i32>();
|
||||||
let fut_values = async move {
|
let fut_values = async move {
|
||||||
let fut_tx_result = async move {
|
let fut_tx_result = async move {
|
||||||
(0..20).for_each(|v| {
|
(0..200).for_each(|v| {
|
||||||
tx.unbounded_send(v).expect("Failed to send");
|
tx.unbounded_send(v).expect("Failed to send");
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
pool.spawn_ok(fut_tx_result);
|
pool.spawn_ok(fut_tx_result);
|
||||||
let fut_values = rx.map(|v| v * 2).collect::<Vec<i32>>();
|
let fut = rx.map(|v| v * 2).collect::<Vec<i32>>();
|
||||||
let results = fut_values.await;
|
let results = fut.await;
|
||||||
if !cfg!(windows) {
|
|
||||||
println!("Collected result lenght {}", results.len());
|
println!("Collected result lenght {}", results.len());
|
||||||
};
|
Ok(results.len() as u32)
|
||||||
async_context.enter(|env| {
|
|
||||||
env
|
|
||||||
.resolve_deferred(deferred, env.get_undefined().unwrap())
|
|
||||||
.unwrap();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
env.create_executor().execute(fut_values);
|
env.perform_async_operation(fut_values, |&mut env, len| env.create_uint32(len))
|
||||||
|
|
||||||
Ok(promise)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[js_function]
|
#[js_function]
|
||||||
fn test_throw<'a>(_ctx: CallContext<'a>) -> Result<Value<'a, Any>> {
|
fn test_throw(_ctx: CallContext) -> Result<Value<Any>> {
|
||||||
Err(Error::new(Status::GenericFailure))
|
Err(Error::from_status(Status::GenericFailure))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue