Skip to content

Commit

Permalink
- Object::method()
Browse files Browse the repository at this point in the history
- BindOptions::exec()
- rename BindOptions::apply() to BindOptions::call()
- eliminate call_method_with() from API docs
  • Loading branch information
dherman committed Sep 28, 2024
1 parent 3d264bc commit 7f1d108
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 28 deletions.
7 changes: 3 additions & 4 deletions crates/neon/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@
//! # use neon::prelude::*;
//! fn log(cx: &mut Cx, msg: &str) -> NeonResult<()> {
//! cx.global::<JsObject>("console")?
//! .call_method_with(cx, "log")?
//! .arg(cx.string(msg))
//! .exec(cx)?;
//!
//! .method(cx, "log")?
//! .arg(msg)?
//! .exec()?;
//! Ok(())
//! }
//!
Expand Down
31 changes: 26 additions & 5 deletions crates/neon/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
/// # }
/// ```
Expand Down Expand Up @@ -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<BindOptions<'a, 'cx>> {
let callee: Handle<JsValue> = self.this.get(self.cx, self.key)?;
let this = Some(self.this.upcast());
Expand Down Expand Up @@ -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<BindOptions<'a, 'cx>> {
let callee: Handle<JsValue> = 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,
Expand Down
6 changes: 3 additions & 3 deletions crates/neon/src/types_impl/extract/with.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ use crate::{context::Cx, result::JsResult, types::extract::TryIntoJs};
///
/// With(move |cx| -> NeonResult<_> {
/// cx.global::<JsObject>("console")?
/// .call_method_with(cx, "log")?
/// .arg(cx.string(log))
/// .exec(cx)?;
/// .method(cx, "log")?
/// .arg(&log)?
/// .exec()?;
///
/// Ok(sum)
/// })
Expand Down
12 changes: 10 additions & 2 deletions crates/neon/src/types_impl/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub(crate) mod private;
/// let x: f64 = parse_int
/// .bind(&mut cx)
/// .arg("42")?
/// .apply()?;
/// .call()?;
/// # Ok(cx.number(x))
/// # }
/// ```
Expand Down Expand Up @@ -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<R: TryFromJs<'cx>>(&mut self) -> NeonResult<R> {
pub fn call<R: TryFromJs<'cx>>(&mut self) -> NeonResult<R> {
let this = self.this.unwrap_or_else(|| self.cx.undefined().upcast());
let v: Handle<JsValue> = 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<JsValue> = self.call()?;
Ok(())
}
}

/// A builder for making a JavaScript function call like `parseInt("42")`.
Expand Down
11 changes: 6 additions & 5 deletions crates/neon/src/types_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
/// # }
/// ```
Expand Down Expand Up @@ -273,11 +273,12 @@ impl ValueInternal for JsUndefined {
/// ```
/// # use neon::prelude::*;
/// # fn test(mut cx: FunctionContext) -> JsResult<JsNull> {
/// let null = cx.null();
/// cx.global::<JsObject>("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)]
Expand Down
12 changes: 6 additions & 6 deletions test/napi/src/js/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub fn call_js_function_with_bind(mut cx: FunctionContext) -> JsResult<JsNumber>
.args((1, 2, 3))?
.arg(4)?
.arg_with(|cx| cx.number(5))?
.apply()?;
.call()?;
Ok(cx.number(n))
}

Expand All @@ -42,7 +42,7 @@ pub fn call_js_function_with_bind_and_args_with(mut cx: FunctionContext) -> JsRe
.argument::<JsFunction>(0)?
.bind(&mut cx)
.args_with(|_| (1, 2, 3))?
.apply()?;
.call()?;
Ok(cx.number(n))
}

Expand All @@ -51,26 +51,26 @@ pub fn call_js_function_with_bind_and_args_and_with(mut cx: FunctionContext) ->
.argument::<JsFunction>(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<JsNumber> {
let parse_int: Handle<JsFunction> = 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))
}

pub fn bind_js_function_to_object(mut cx: FunctionContext) -> JsResult<JsValue> {
let f = cx.argument::<JsFunction>(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<JsValue> {
let f = cx.argument::<JsFunction>(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> {
Expand Down
6 changes: 3 additions & 3 deletions test/napi/src/js/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ pub fn call_methods_with_prop(mut cx: FunctionContext) -> JsResult<JsString> {
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<JsUndefined> {
let obj: Handle<JsObject> = cx.argument::<JsObject>(0)?;
obj.prop(&mut cx, "number").bind()?.apply()?;
obj.prop(&mut cx, "number").bind()?.call()?;
Ok(cx.undefined())
}

0 comments on commit 7f1d108

Please sign in to comment.