diff --git a/napi-derive/src/lib.rs b/napi-derive/src/lib.rs index a03631a6..08c4bb5f 100644 --- a/napi-derive/src/lib.rs +++ b/napi-derive/src/lib.rs @@ -85,9 +85,10 @@ pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream { let new_fn_name = signature.ident.clone(); let execute_js_function = get_execute_js_code(new_fn_name, FunctionKind::JsFunction); let expanded = quote! { - #[inline] + #[inline(always)] #signature #(#fn_block)* + #[inline(always)] #visibility extern "C" fn #fn_name( raw_env: napi::sys::napi_env, cb_info: napi::sys::napi_callback_info, diff --git a/napi/src/js_values/function.rs b/napi/src/js_values/function.rs index 6d456260..934726ec 100644 --- a/napi/src/js_values/function.rs +++ b/napi/src/js_values/function.rs @@ -55,4 +55,28 @@ impl JsFunction { JsUnknown::from_raw(self.0.env, return_value) } + + /// https://nodejs.org/api/n-api.html#n_api_napi_new_instance + /// This method is used to instantiate a new `JavaScript` value using a given `JsFunction` that represents the constructor for the object. + pub fn new(&self, args: &[V]) -> Result + where + V: NapiValue, + { + let mut js_instance = ptr::null_mut(); + let length = args.len() as u64; + let raw_args = args + .iter() + .map(|arg| arg.raw()) + .collect::>(); + check_status(unsafe { + sys::napi_new_instance( + self.0.env, + self.0.value, + length, + raw_args.as_ptr(), + &mut js_instance, + ) + })?; + Ok(JsObject::from_raw_unchecked(self.0.env, js_instance)) + } } diff --git a/test_module/__test__/class.spec.ts b/test_module/__test__/class.spec.ts index d681097d..3c5b801e 100644 --- a/test_module/__test__/class.spec.ts +++ b/test_module/__test__/class.spec.ts @@ -19,3 +19,8 @@ test('should be able to manipulate wrapped native value', (t) => { const add = 101 t.is(testClass.addNativeCount(add), fixture + add + 100) }) + +test('should be able to new class instance in native side', (t) => { + const instance = bindings.newTestClass() + t.is(instance.count, 42) +}) diff --git a/test_module/src/class.rs b/test_module/src/class.rs index d62c27b5..58de0572 100644 --- a/test_module/src/class.rs +++ b/test_module/src/class.rs @@ -45,7 +45,21 @@ fn add_native_count(ctx: CallContext) -> Result { ctx.env.create_int32(native_class.value) } +#[js_function(1)] +fn new_test_class(ctx: CallContext) -> Result { + let add_count_method = Property::new(&ctx.env, "addCount")?.with_method(add_count); + let add_native_count = Property::new(&ctx.env, "addNativeCount")?.with_method(add_native_count); + let properties = vec![add_count_method, add_native_count]; + let test_class = + ctx + .env + .define_class("TestClass", test_class_constructor, properties.as_slice())?; + + test_class.new(&vec![ctx.env.create_int32(42)?]) +} + pub fn register_js(module: &mut Module) -> Result<()> { module.create_named_method("createTestClass", create_test_class)?; + module.create_named_method("newTestClass", new_test_class)?; Ok(()) }