Merge pull request #1064 from napi-rs/feature/obj-property-value
feat(napi): `with_value` method on `Property`
This commit is contained in:
commit
2cd105cfc6
9 changed files with 86 additions and 5 deletions
|
@ -211,6 +211,38 @@ pub fn get_js_function(raw_fn: ExportRegisterCallback) -> Result<JsFunction> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get `C Callback` from defined Rust `fn`
|
||||||
|
/// ```rust
|
||||||
|
/// #[napi]
|
||||||
|
/// fn some_fn() -> u32 {
|
||||||
|
/// 1
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// #[napi]
|
||||||
|
/// fn create_obj(env: Env) -> Result<JsObject> {
|
||||||
|
/// let mut obj = env.create_object()?;
|
||||||
|
/// obj.define_property(&[Property::new("getter")?.with_getter(get_c_callback(some_fn_js_function)?)])?;
|
||||||
|
/// Ok(obj)
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```js
|
||||||
|
/// console.log(createObj().getter) // 1
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
pub fn get_c_callback(raw_fn: ExportRegisterCallback) -> Result<crate::Callback> {
|
||||||
|
FN_REGISTER_MAP
|
||||||
|
.borrow_mut()
|
||||||
|
.get(&raw_fn)
|
||||||
|
.and_then(|(_env, cb, _name)| *cb)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
crate::Error::new(
|
||||||
|
crate::Status::InvalidArg,
|
||||||
|
"JavaScript function does not exists".to_owned(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn napi_register_module_v1(
|
unsafe extern "C" fn napi_register_module_v1(
|
||||||
env: sys::napi_env,
|
env: sys::napi_env,
|
||||||
|
|
|
@ -31,7 +31,7 @@ use serde::Serialize;
|
||||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
pub type Callback = extern "C" fn(sys::napi_env, sys::napi_callback_info) -> sys::napi_value;
|
pub type Callback = unsafe extern "C" fn(sys::napi_env, sys::napi_callback_info) -> sys::napi_value;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
/// `Env` is used to represent a context that the underlying N-API implementation can use to persist VM-specific state.
|
/// `Env` is used to represent a context that the underlying N-API implementation can use to persist VM-specific state.
|
||||||
|
|
|
@ -2,18 +2,33 @@ use std::convert::From;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use crate::{sys, Callback, Result};
|
use crate::{sys, Callback, NapiRaw, Result};
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone)]
|
||||||
pub struct Property {
|
pub struct Property {
|
||||||
pub name: CString,
|
pub name: CString,
|
||||||
getter: sys::napi_callback,
|
getter: sys::napi_callback,
|
||||||
setter: sys::napi_callback,
|
setter: sys::napi_callback,
|
||||||
method: sys::napi_callback,
|
method: sys::napi_callback,
|
||||||
attrs: PropertyAttributes,
|
attrs: PropertyAttributes,
|
||||||
|
value: sys::napi_value,
|
||||||
pub(crate) is_ctor: bool,
|
pub(crate) is_ctor: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Property {
|
||||||
|
fn default() -> Self {
|
||||||
|
Property {
|
||||||
|
name: Default::default(),
|
||||||
|
getter: Default::default(),
|
||||||
|
setter: Default::default(),
|
||||||
|
method: Default::default(),
|
||||||
|
attrs: Default::default(),
|
||||||
|
value: ptr::null_mut(),
|
||||||
|
is_ctor: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum PropertyAttributes {
|
pub enum PropertyAttributes {
|
||||||
|
@ -75,6 +90,11 @@ impl Property {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_value<T: NapiRaw>(mut self, value: &T) -> Self {
|
||||||
|
self.value = unsafe { T::raw(value) };
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn raw(&self) -> sys::napi_property_descriptor {
|
pub(crate) fn raw(&self) -> sys::napi_property_descriptor {
|
||||||
sys::napi_property_descriptor {
|
sys::napi_property_descriptor {
|
||||||
utf8name: self.name.as_ptr(),
|
utf8name: self.name.as_ptr(),
|
||||||
|
@ -82,7 +102,7 @@ impl Property {
|
||||||
method: self.method,
|
method: self.method,
|
||||||
getter: self.getter,
|
getter: self.getter,
|
||||||
setter: self.setter,
|
setter: self.setter,
|
||||||
value: ptr::null_mut(),
|
value: self.value,
|
||||||
attributes: self.attrs.into(),
|
attributes: self.attrs.into(),
|
||||||
data: ptr::null_mut(),
|
data: ptr::null_mut(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,8 @@ Generated by [AVA](https://avajs.dev).
|
||||||
typeOverride: object␊
|
typeOverride: object␊
|
||||||
typeOverrideOptional?: object␊
|
typeOverrideOptional?: object␊
|
||||||
}␊
|
}␊
|
||||||
|
export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number }␊
|
||||||
|
export function getterFromObj(): number␊
|
||||||
export function asyncPlus100(p: Promise<number>): Promise<number>␊
|
export function asyncPlus100(p: Promise<number>): Promise<number>␊
|
||||||
/** This is an interface for package.json */␊
|
/** This is an interface for package.json */␊
|
||||||
export interface PackageJson {␊
|
export interface PackageJson {␊
|
||||||
|
|
Binary file not shown.
|
@ -81,6 +81,7 @@ import {
|
||||||
getStrFromObject,
|
getStrFromObject,
|
||||||
returnJsFunction,
|
returnJsFunction,
|
||||||
testSerdeRoundtrip,
|
testSerdeRoundtrip,
|
||||||
|
createObjWithProperty,
|
||||||
} from '../'
|
} from '../'
|
||||||
|
|
||||||
test('export const', (t) => {
|
test('export const', (t) => {
|
||||||
|
@ -220,6 +221,12 @@ test('get str from object', (t) => {
|
||||||
t.notThrows(() => getStrFromObject())
|
t.notThrows(() => getStrFromObject())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('create object from Property', (t) => {
|
||||||
|
const obj = createObjWithProperty()
|
||||||
|
t.true(obj.value instanceof ArrayBuffer)
|
||||||
|
t.is(obj.getter, 42)
|
||||||
|
})
|
||||||
|
|
||||||
test('global', (t) => {
|
test('global', (t) => {
|
||||||
t.is(getGlobal(), global)
|
t.is(getGlobal(), global)
|
||||||
})
|
})
|
||||||
|
|
2
examples/napi/index.d.ts
vendored
2
examples/napi/index.d.ts
vendored
|
@ -102,6 +102,8 @@ export interface TsTypeChanged {
|
||||||
typeOverride: object
|
typeOverride: object
|
||||||
typeOverrideOptional?: object
|
typeOverrideOptional?: object
|
||||||
}
|
}
|
||||||
|
export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number }
|
||||||
|
export function getterFromObj(): number
|
||||||
export function asyncPlus100(p: Promise<number>): Promise<number>
|
export function asyncPlus100(p: Promise<number>): Promise<number>
|
||||||
/** This is an interface for package.json */
|
/** This is an interface for package.json */
|
||||||
export interface PackageJson {
|
export interface PackageJson {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate napi_derive;
|
extern crate napi_derive;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use napi::{bindgen_prelude::*, JsGlobal, JsNull, JsUndefined};
|
use napi::{bindgen_prelude::*, JsGlobal, JsNull, JsObject, JsUndefined, Property};
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
fn list_obj_keys(obj: Object) -> Vec<String> {
|
fn list_obj_keys(obj: Object) -> Vec<String> {
|
||||||
|
@ -85,3 +85,19 @@ pub struct TsTypeChanged {
|
||||||
#[napi(ts_type = "object")]
|
#[napi(ts_type = "object")]
|
||||||
pub type_override_optional: Option<String>,
|
pub type_override_optional: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[napi(ts_return_type = "{ value: ArrayBuffer, get getter(): number }")]
|
||||||
|
pub fn create_obj_with_property(env: Env) -> Result<JsObject> {
|
||||||
|
let mut obj = env.create_object()?;
|
||||||
|
let arraybuffer = env.create_arraybuffer(10)?.into_raw();
|
||||||
|
obj.define_properties(&[
|
||||||
|
Property::new("value")?.with_value(&arraybuffer),
|
||||||
|
Property::new("getter")?.with_getter(get_c_callback(getter_from_obj_js_function)?),
|
||||||
|
])?;
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
fn getter_from_obj() -> u32 {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue