diff --git a/crates/neon/src/context/mod.rs b/crates/neon/src/context/mod.rs index 8e4ff88bf..ad8d338b6 100644 --- a/crates/neon/src/context/mod.rs +++ b/crates/neon/src/context/mod.rs @@ -45,10 +45,9 @@ //! # use neon::prelude::*; //! fn log(cx: &mut Cx, msg: &str) -> NeonResult<()> { //! cx.global::("console")? -//! .call_method_with(cx, "log")? -//! .arg(cx.string(msg)) -//! .exec(cx)?; -//! +//! .method(cx, "log")? +//! .arg(msg)? +//! .exec()?; //! Ok(()) //! } //! diff --git a/crates/neon/src/object/mod.rs b/crates/neon/src/object/mod.rs index 43d33f3fd..c54b60fb2 100644 --- a/crates/neon/src/object/mod.rs +++ b/crates/neon/src/object/mod.rs @@ -157,9 +157,7 @@ impl<'a> PropertyKey for &'a str { /// obj.prop(&mut cx, "y") /// .set(x)?; /// -/// let s: String = obj.prop(&mut cx, "toString") -/// .bind()? -/// .apply()?; +/// let s: String = obj.method(&mut cx, "toString")?.call()?; /// # Ok(cx.string(s)) /// # } /// ``` @@ -241,8 +239,9 @@ where /// Gets the property from the object as a method and binds `this` to the object. /// - /// May throw an exception either during accessing the property or downcasting it - /// to a function. + /// May throw an exception when accessing the property. + /// + /// Defers checking that the method is callable until call time. pub fn bind(&'a mut self) -> NeonResult> { let callee: Handle = self.this.get(self.cx, self.key)?; let this = Some(self.this.upcast()); @@ -276,6 +275,28 @@ pub trait Object: Value { PropOptions { cx, this, key } } + /// Gets a property from the object as a method and binds `this` to the object. + /// + /// May throw an exception either from accessing the property. + /// + /// Defers checking that the method is callable until call time. + fn method<'a, 'cx: 'a, K: PropertyKey>( + &self, + cx: &'a mut Cx<'cx>, + key: K, + ) -> NeonResult> { + let callee: Handle = self + .prop(cx, key) + .get()?; + let this = Some(self.as_value(cx)); + Ok(BindOptions { + cx, + callee, + this, + args: smallvec![], + }) + } + #[doc(hidden)] fn get_opt<'a, V: Value, C: Context<'a>, K: PropertyKey>( &self, diff --git a/crates/neon/src/types_impl/extract/with.rs b/crates/neon/src/types_impl/extract/with.rs index 0f631fe8a..bfce5c03f 100644 --- a/crates/neon/src/types_impl/extract/with.rs +++ b/crates/neon/src/types_impl/extract/with.rs @@ -20,9 +20,9 @@ use crate::{context::Cx, result::JsResult, types::extract::TryIntoJs}; /// /// With(move |cx| -> NeonResult<_> { /// cx.global::("console")? -/// .call_method_with(cx, "log")? -/// .arg(cx.string(log)) -/// .exec(cx)?; +/// .method(cx, "log")? +/// .arg(&log)? +/// .exec()?; /// /// Ok(sum) /// }) diff --git a/crates/neon/src/types_impl/function/mod.rs b/crates/neon/src/types_impl/function/mod.rs index 25ded38af..a82964ae2 100644 --- a/crates/neon/src/types_impl/function/mod.rs +++ b/crates/neon/src/types_impl/function/mod.rs @@ -26,7 +26,7 @@ pub(crate) mod private; /// let x: f64 = parse_int /// .bind(&mut cx) /// .arg("42")? -/// .apply()?; +/// .call()?; /// # Ok(cx.number(x)) /// # } /// ``` @@ -81,11 +81,19 @@ impl<'a, 'cx: 'a> BindOptions<'a, 'cx> { /// Make the function call. If the function returns without throwing, the result value /// is converted to a Rust value with `TryFromJs::from_js`. - pub fn apply>(&mut self) -> NeonResult { + pub fn call>(&mut self) -> NeonResult { let this = self.this.unwrap_or_else(|| self.cx.undefined().upcast()); let v: Handle = unsafe { self.callee.try_call(self.cx, this, &self.args)? }; R::from_js(self.cx, v) } + + /// Make the function call for side effect, discarding the result value. This method is + /// preferable to [`call()`](BindOptions::call) when the result value isn't needed, + /// since it doesn't require specifying a result type. + pub fn exec(&mut self) -> NeonResult<()> { + let _ignore: Handle = self.call()?; + Ok(()) + } } /// A builder for making a JavaScript function call like `parseInt("42")`. diff --git a/crates/neon/src/types_impl/mod.rs b/crates/neon/src/types_impl/mod.rs index ad4c9202e..e9c254572 100644 --- a/crates/neon/src/types_impl/mod.rs +++ b/crates/neon/src/types_impl/mod.rs @@ -208,7 +208,7 @@ impl JsValue { /// let undefined = cx.undefined(); /// /// // Call console.log(undefined): -/// console.call_method_with(&mut cx, "log")?.arg(undefined).exec(&mut cx)?; +/// console.method(&mut cx, "log")?.arg(undefined)?.exec()?; /// # Ok(undefined) /// # } /// ``` @@ -273,11 +273,12 @@ impl ValueInternal for JsUndefined { /// ``` /// # use neon::prelude::*; /// # fn test(mut cx: FunctionContext) -> JsResult { +/// let null = cx.null(); /// cx.global::("console")? -/// .call_method_with(&mut cx, "log")? -/// .arg(cx.null()) -/// .exec(&mut cx)?; -/// # Ok(cx.null()) +/// .method(&mut cx, "log")? +/// .arg(null)? +/// .exec()?; +/// # Ok(null) /// # } /// ``` #[derive(Debug)] diff --git a/test/napi/src/js/functions.rs b/test/napi/src/js/functions.rs index ff0b721ab..b95d4f10a 100644 --- a/test/napi/src/js/functions.rs +++ b/test/napi/src/js/functions.rs @@ -33,7 +33,7 @@ pub fn call_js_function_with_bind(mut cx: FunctionContext) -> JsResult .args((1, 2, 3))? .arg(4)? .arg_with(|cx| cx.number(5))? - .apply()?; + .call()?; Ok(cx.number(n)) } @@ -42,7 +42,7 @@ pub fn call_js_function_with_bind_and_args_with(mut cx: FunctionContext) -> JsRe .argument::(0)? .bind(&mut cx) .args_with(|_| (1, 2, 3))? - .apply()?; + .call()?; Ok(cx.number(n)) } @@ -51,13 +51,13 @@ pub fn call_js_function_with_bind_and_args_and_with(mut cx: FunctionContext) -> .argument::(0)? .bind(&mut cx) .args(With(|_| (1, 2, 3)))? - .apply()?; + .call()?; Ok(cx.number(n)) } pub fn call_parse_int_with_bind(mut cx: FunctionContext) -> JsResult { let parse_int: Handle = cx.global("parseInt")?; - let x: f64 = parse_int.bind(&mut cx).arg("41")?.apply()?; + let x: f64 = parse_int.bind(&mut cx).arg("41")?.call()?; Ok(cx.number(x + 1.0)) } @@ -65,12 +65,12 @@ pub fn bind_js_function_to_object(mut cx: FunctionContext) -> JsResult let f = cx.argument::(0)?; let obj = cx.empty_object(); obj.prop(&mut cx, "prop").set(42)?; - f.bind(&mut cx).this(obj)?.apply() + f.bind(&mut cx).this(obj)?.call() } pub fn bind_js_function_to_number(mut cx: FunctionContext) -> JsResult { let f = cx.argument::(0)?; - f.bind(&mut cx).this(42)?.apply() + f.bind(&mut cx).this(42)?.call() } fn get_math_max<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsFunction> { diff --git a/test/napi/src/js/objects.rs b/test/napi/src/js/objects.rs index d5a8b0091..32b1f1815 100644 --- a/test/napi/src/js/objects.rs +++ b/test/napi/src/js/objects.rs @@ -113,12 +113,12 @@ pub fn call_methods_with_prop(mut cx: FunctionContext) -> JsResult { obj.prop(&mut cx, "setName") .bind()? .arg("Wonder Woman")? - .apply()?; - obj.prop(&mut cx, "toString").bind()?.apply() + .call()?; + obj.prop(&mut cx, "toString").bind()?.call() } pub fn call_non_method_with_prop(mut cx: FunctionContext) -> JsResult { let obj: Handle = cx.argument::(0)?; - obj.prop(&mut cx, "number").bind()?.apply()?; + obj.prop(&mut cx, "number").bind()?.call()?; Ok(cx.undefined()) }