From 9c018a76e44fb50dd9b1cfc36d6567ce8f6aa20c Mon Sep 17 00:00:00 2001 From: David Herman Date: Sun, 8 Sep 2024 13:59:55 -0700 Subject: [PATCH] add a test case and get rid of unneeded sys helper --- crates/neon/src/sys/fun.rs | 20 -------------------- crates/neon/src/types_impl/mod.rs | 31 ++++++++++++++++++++++++++----- test/napi/lib/objects.js | 8 ++++++++ test/napi/src/js/objects.rs | 8 ++++++++ test/napi/src/lib.rs | 1 + 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/crates/neon/src/sys/fun.rs b/crates/neon/src/sys/fun.rs index e4a709d39..fffd03cc3 100644 --- a/crates/neon/src/sys/fun.rs +++ b/crates/neon/src/sys/fun.rs @@ -83,26 +83,6 @@ where callback(env, info) } -pub unsafe fn call( - out: &mut Local, - env: Env, - fun: Local, - this: Local, - argc: i32, - argv: *const c_void, -) -> bool { - let status = napi::call_function( - env, - this, - fun, - argc as usize, - argv as *const _, - out as *mut _, - ); - - status == napi::Status::Ok -} - pub unsafe fn construct( out: &mut Local, env: Env, diff --git a/crates/neon/src/types_impl/mod.rs b/crates/neon/src/types_impl/mod.rs index 86013230c..a99376c8a 100644 --- a/crates/neon/src/types_impl/mod.rs +++ b/crates/neon/src/types_impl/mod.rs @@ -31,7 +31,7 @@ use crate::{ }, object::Object, result::{JsResult, NeonResult, ResultExt, Throw}, - sys::{self, raw}, + sys::{self, bindings as napi, raw}, types::{ function::{BindOptions, CallOptions, ConstructOptions}, private::ValueInternal, @@ -1165,10 +1165,31 @@ where AS: AsRef<[Handle<'b, JsValue>]>, { let (argc, argv) = unsafe { prepare_call(cx, args.as_ref()) }?; - let env = cx.env().to_raw(); - build(cx.env(), |out| unsafe { - sys::fun::call(out, env, callee, this.to_local(), argc, argv) - }) + let env = cx.env(); + let result: raw::Local = std::mem::zeroed(); + + let status = napi::call_function( + env.to_raw(), + this.to_local(), + callee, + argc as usize, + argv as *const _, + result as *mut _, + ); + + match status { + sys::Status::FunctionExpected => { + return cx.throw_type_error("not a function"); + } + sys::Status::PendingException => { + return Err(Throw::new()); + } + status => { + assert_eq!(status, sys::Status::Ok); + } + } + + Ok(Handle::new_internal(JsValue::from_local(env, result))) } impl JsFunction { diff --git a/test/napi/lib/objects.js b/test/napi/lib/objects.js index 4b444a6ab..bc89add8d 100644 --- a/test/napi/lib/objects.js +++ b/test/napi/lib/objects.js @@ -157,4 +157,12 @@ describe("JsObject", function () { ); assert.strictEqual(obj.toString(), "[object Wonder Woman]"); }); + + it("throws a TypeError when calling a non-method with .prop()", function () { + const obj = { + number: 42 + }; + + assert.throws(() => { addon.call_non_method_with_prop(obj) }, /not a function/); + }) }); diff --git a/test/napi/src/js/objects.rs b/test/napi/src/js/objects.rs index 76a181816..78689428b 100644 --- a/test/napi/src/js/objects.rs +++ b/test/napi/src/js/objects.rs @@ -116,3 +116,11 @@ pub fn call_methods_with_prop(mut cx: FunctionContext) -> JsResult { .apply()?; obj.prop(&mut cx, "toString").bind()?.apply() } + +pub fn call_non_method_with_prop(mut cx: FunctionContext) -> JsResult { + let obj: Handle = cx.argument::(0)?; + obj.prop(&mut cx, "number") + .bind()? + .apply()?; + Ok(cx.undefined()) +} \ No newline at end of file diff --git a/test/napi/src/lib.rs b/test/napi/src/lib.rs index e9d0d4916..2dac42d65 100644 --- a/test/napi/src/lib.rs +++ b/test/napi/src/lib.rs @@ -296,6 +296,7 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> { cx.export_function("get_property_with_prop", get_property_with_prop)?; cx.export_function("set_property_with_prop", set_property_with_prop)?; cx.export_function("call_methods_with_prop", call_methods_with_prop)?; + cx.export_function("call_non_method_with_prop", call_non_method_with_prop)?; cx.export_function("create_date", create_date)?; cx.export_function("get_date_value", get_date_value)?;