Merge pull request #76 from napi-rs/create-external
feat(napi): implement create_external and get_value_external
This commit is contained in:
commit
91c1ab9ea4
5 changed files with 82 additions and 3 deletions
|
@ -136,7 +136,7 @@ npm test
|
|||
| [napi_create_buffer](https://nodejs.org/api/n-api.html#n_api_napi_create_buffer) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_create_buffer_copy](https://nodejs.org/api/n-api.html#n_api_napi_create_buffer_copy) | 1 | v8.0.0 | ⛔️ |
|
||||
| [napi_create_date](https://nodejs.org/api/n-api.html#n_api_napi_create_date) | 5 | v11.11.0 | ⛔️ |
|
||||
| [napi_create_external](https://nodejs.org/api/n-api.html#n_api_napi_create_external) | 1 | v8.0.0 | ⛔️ |
|
||||
| [napi_create_external](https://nodejs.org/api/n-api.html#n_api_napi_create_external) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_create_external_arraybuffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_arraybuffer) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_create_external_buffer](https://nodejs.org/api/n-api.html#n_api_napi_create_external_buffer) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_create_object](https://nodejs.org/api/n-api.html#n_api_napi_create_object) | 1 | v8.0.0 | ✅ |
|
||||
|
|
|
@ -530,6 +530,48 @@ impl Env {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_external<T: 'static>(&self, native_object: T) -> Result<Value<Object>> {
|
||||
let mut object_value = ptr::null_mut();
|
||||
let status = unsafe {
|
||||
sys::napi_create_external(
|
||||
self.0,
|
||||
Box::into_raw(Box::new(TaggedObject::new(native_object))) as *mut c_void,
|
||||
Some(raw_finalize::<T>),
|
||||
ptr::null_mut(),
|
||||
&mut object_value,
|
||||
)
|
||||
};
|
||||
|
||||
check_status(status)?;
|
||||
Ok(Value::from_raw_value(self, object_value, Object))
|
||||
}
|
||||
|
||||
pub fn get_value_external<T: 'static>(&self, js_object: &Value<Object>) -> Result<&mut T> {
|
||||
unsafe {
|
||||
let mut unknown_tagged_object = ptr::null_mut();
|
||||
let status =
|
||||
sys::napi_get_value_external(self.0, js_object.raw_value, &mut unknown_tagged_object);
|
||||
check_status(status)?;
|
||||
|
||||
let type_id: *const TypeId = mem::transmute(unknown_tagged_object);
|
||||
if *type_id == TypeId::of::<T>() {
|
||||
let tagged_object: *mut TaggedObject<T> = mem::transmute(unknown_tagged_object);
|
||||
(*tagged_object).object.as_mut().ok_or(Error {
|
||||
status: Status::InvalidArg,
|
||||
reason: Some("Invalid argument, nothing attach to js_object".to_owned()),
|
||||
})
|
||||
} else {
|
||||
Err(Error {
|
||||
status: Status::InvalidArg,
|
||||
reason: Some(
|
||||
"Invalid argument, T on get_value_external is not the type of wrapped object"
|
||||
.to_owned(),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_error(&self, e: Error) -> Result<Value<Object>> {
|
||||
let reason = e.reason.unwrap_or("".to_owned());
|
||||
let reason_string = self.create_string(reason.as_str())?;
|
||||
|
|
|
@ -4,7 +4,7 @@ pub trait Task {
|
|||
type Output: Send + Sized + 'static;
|
||||
type JsValue: ValueType;
|
||||
|
||||
fn compute(&self) -> Result<Self::Output>;
|
||||
fn compute(&mut self) -> Result<Self::Output>;
|
||||
|
||||
fn resolve(&self, env: &mut Env, output: Self::Output) -> Result<Value<Self::JsValue>>;
|
||||
}
|
||||
|
|
9
test_module/__test__/create-external.spec.js
Normal file
9
test_module/__test__/create-external.spec.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
const test = require('ava')
|
||||
|
||||
const bindings = require('../index.node')
|
||||
|
||||
test('should create external object and get it back', (t) => {
|
||||
const fixture = 42
|
||||
const externalObject = bindings.createExternal(42)
|
||||
t.is(bindings.getExternalCount(externalObject), fixture)
|
||||
})
|
|
@ -24,6 +24,16 @@ fn init(env: &Env, exports: &mut Value<Object>) -> Result<()> {
|
|||
"testObjectIsDate",
|
||||
env.create_function("testObjectIsDate", test_object_is_date)?,
|
||||
)?;
|
||||
|
||||
exports.set_named_property(
|
||||
"createExternal",
|
||||
env.create_function("createExternal", create_external)?,
|
||||
)?;
|
||||
|
||||
exports.set_named_property(
|
||||
"getExternalCount",
|
||||
env.create_function("getExternalCount", get_external_count)?,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -41,7 +51,7 @@ impl Task for ComputeFib {
|
|||
type Output = u32;
|
||||
type JsValue = Number;
|
||||
|
||||
fn compute(&self) -> Result<Self::Output> {
|
||||
fn compute(&mut self) -> Result<Self::Output> {
|
||||
Ok(fibonacci_native(self.n))
|
||||
}
|
||||
|
||||
|
@ -84,3 +94,21 @@ fn test_object_is_date(ctx: CallContext) -> Result<Value<Boolean>> {
|
|||
let obj: Value<Object> = ctx.get::<Object>(0)?;
|
||||
Ok(Env::get_boolean(ctx.env, obj.is_date()?)?)
|
||||
}
|
||||
|
||||
struct NativeObject {
|
||||
count: i32,
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
fn create_external(ctx: CallContext) -> Result<Value<Object>> {
|
||||
let count = ctx.get::<Number>(0)?.try_into()?;
|
||||
let native = NativeObject { count };
|
||||
ctx.env.create_external(native)
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
fn get_external_count(ctx: CallContext) -> Result<Value<Number>> {
|
||||
let attached_obj = ctx.get::<Object>(0)?;
|
||||
let native_object = ctx.env.get_value_external::<NativeObject>(&attached_obj)?;
|
||||
ctx.env.create_int32(native_object.count)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue