From e8941aa9eaa58ff6182956e54756ded1b2793d91 Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 29 Oct 2021 06:40:38 -0700 Subject: [PATCH 1/8] Rename `neon::types::internal` to `neon::types::private`. --- src/object/class/mod.rs | 2 +- src/types/binary.rs | 2 +- src/types/boxed.rs | 2 +- src/types/buffer/types.rs | 2 +- src/types/date.rs | 2 +- src/types/error.rs | 2 +- src/types/mod.rs | 25 ++++++++++++------------- src/types/{internal.rs => private.rs} | 0 src/types/promise.rs | 2 +- 9 files changed, 19 insertions(+), 20 deletions(-) rename src/types/{internal.rs => private.rs} (100%) diff --git a/src/object/class/mod.rs b/src/object/class/mod.rs index dff27a59e..8a12b054b 100644 --- a/src/object/class/mod.rs +++ b/src/object/class/mod.rs @@ -11,7 +11,7 @@ use crate::context::{Context, Lock}; use crate::handle::{Handle, Managed}; use crate::object::{Object, This}; use crate::result::{JsResult, NeonResult, Throw}; -use crate::types::internal::{Callback, ValueInternal}; +use crate::types::private::{Callback, ValueInternal}; use crate::types::{build, JsFunction, JsValue, Value}; use neon_runtime; use neon_runtime::raw; diff --git a/src/types/binary.rs b/src/types/binary.rs index 98dba5d27..f9434fc53 100644 --- a/src/types/binary.rs +++ b/src/types/binary.rs @@ -4,7 +4,7 @@ use crate::context::internal::Env; use crate::context::{Context, Lock}; use crate::handle::Managed; use crate::result::JsResult; -use crate::types::internal::ValueInternal; +use crate::types::private::ValueInternal; use crate::types::{build, Object, Value}; use neon_runtime; use neon_runtime::raw; diff --git a/src/types/boxed.rs b/src/types/boxed.rs index d687e2064..867e81157 100644 --- a/src/types/boxed.rs +++ b/src/types/boxed.rs @@ -8,7 +8,7 @@ use crate::context::internal::Env; use crate::context::{Context, FinalizeContext}; use crate::handle::{Handle, Managed}; use crate::object::Object; -use crate::types::internal::ValueInternal; +use crate::types::private::ValueInternal; use crate::types::Value; type BoxAny = Box; diff --git a/src/types/buffer/types.rs b/src/types/buffer/types.rs index b24a23635..dc0bdcf6d 100644 --- a/src/types/buffer/types.rs +++ b/src/types/buffer/types.rs @@ -6,7 +6,7 @@ use neon_runtime::{raw, TypedArrayType}; use crate::context::{internal::Env, Context}; use crate::handle::{Handle, Managed}; use crate::result::{JsResult, Throw}; -use crate::types::{internal::ValueInternal, Object, Value}; +use crate::types::{private::ValueInternal, Object, Value}; use super::lock::{Ledger, Lock}; use super::{private, BorrowError, Ref, RefMut, TypedArray}; diff --git a/src/types/date.rs b/src/types/date.rs index 76c636f6e..0cd639aa7 100644 --- a/src/types/date.rs +++ b/src/types/date.rs @@ -1,4 +1,4 @@ -use super::{Value, ValueInternal}; +use super::{private::ValueInternal, Value}; use crate::context::internal::Env; use crate::context::Context; use crate::handle::{Handle, Managed}; diff --git a/src/types/error.rs b/src/types/error.rs index 3b89589af..3d3416644 100644 --- a/src/types/error.rs +++ b/src/types/error.rs @@ -8,7 +8,7 @@ use neon_runtime::raw; use crate::context::internal::Env; use crate::context::Context; use crate::result::{NeonResult, Throw}; -use crate::types::internal::ValueInternal; +use crate::types::private::ValueInternal; use crate::types::utf8::Utf8; use crate::types::{build, Handle, Managed, Object, Value}; diff --git a/src/types/mod.rs b/src/types/mod.rs index 348fb8028..d04828af7 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -86,10 +86,10 @@ pub(crate) mod error; #[cfg(all(feature = "napi-1", feature = "promise-api"))] pub(crate) mod promise; -pub(crate) mod internal; +pub(crate) mod private; pub(crate) mod utf8; -use self::internal::{FunctionCallback, ValueInternal}; +use self::private::{Callback, FunctionCallback}; use self::utf8::Utf8; use crate::context::internal::Env; use crate::context::{Context, FunctionContext}; @@ -97,7 +97,6 @@ use crate::handle::internal::SuperType; use crate::handle::{Handle, Managed}; use crate::object::{Object, This}; use crate::result::{JsResult, JsResultExt, NeonResult, Throw}; -use crate::types::internal::Callback; use neon_runtime; use neon_runtime::raw; use smallvec::SmallVec; @@ -145,7 +144,7 @@ impl SuperType for JsObject { } /// The trait shared by all JavaScript values. -pub trait Value: ValueInternal { +pub trait Value: private::ValueInternal { fn to_string<'a, C: Context<'a>>(self, cx: &mut C) -> JsResult<'a, JsString> { let env = cx.env(); build(env, |out| unsafe { @@ -175,7 +174,7 @@ impl Managed for JsValue { } } -impl ValueInternal for JsValue { +impl private::ValueInternal for JsValue { fn name() -> String { "any".to_string() } @@ -261,7 +260,7 @@ unsafe impl This for JsUndefined { } } -impl ValueInternal for JsUndefined { +impl private::ValueInternal for JsUndefined { fn name() -> String { "undefined".to_string() } @@ -308,7 +307,7 @@ impl Managed for JsNull { } } -impl ValueInternal for JsNull { +impl private::ValueInternal for JsNull { fn name() -> String { "null".to_string() } @@ -360,7 +359,7 @@ impl Managed for JsBoolean { } } -impl ValueInternal for JsBoolean { +impl private::ValueInternal for JsBoolean { fn name() -> String { "boolean".to_string() } @@ -409,7 +408,7 @@ impl Managed for JsString { } } -impl ValueInternal for JsString { +impl private::ValueInternal for JsString { fn name() -> String { "string".to_string() } @@ -530,7 +529,7 @@ impl Managed for JsNumber { } } -impl ValueInternal for JsNumber { +impl private::ValueInternal for JsNumber { fn name() -> String { "number".to_string() } @@ -569,7 +568,7 @@ unsafe impl This for JsObject { } } -impl ValueInternal for JsObject { +impl private::ValueInternal for JsObject { fn name() -> String { "object".to_string() } @@ -669,7 +668,7 @@ impl Managed for JsArray { } } -impl ValueInternal for JsArray { +impl private::ValueInternal for JsArray { fn name() -> String { "Array".to_string() } @@ -777,7 +776,7 @@ impl Managed for JsFunction { } } -impl ValueInternal for JsFunction { +impl private::ValueInternal for JsFunction { fn name() -> String { "function".to_string() } diff --git a/src/types/internal.rs b/src/types/private.rs similarity index 100% rename from src/types/internal.rs rename to src/types/private.rs diff --git a/src/types/promise.rs b/src/types/promise.rs index d816f4b6c..b325fa033 100644 --- a/src/types/promise.rs +++ b/src/types/promise.rs @@ -12,7 +12,7 @@ use crate::handle::Managed; #[cfg(feature = "napi-6")] use crate::lifecycle::{DropData, InstanceData}; use crate::result::JsResult; -use crate::types::{Handle, Object, Value, ValueInternal}; +use crate::types::{private::ValueInternal, Handle, Object, Value}; #[cfg(feature = "channel-api")] use crate::{ context::TaskContext, From 2e2a0011a8e1409d8af315dfea0409663bef04aa Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 29 Oct 2021 06:44:31 -0700 Subject: [PATCH 2/8] Make `prepare_call` safe and immutable. --- crates/neon-runtime/src/napi/fun.rs | 4 ++-- crates/neon-sys/src/lib.rs | 4 ++-- src/types/mod.rs | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/neon-runtime/src/napi/fun.rs b/crates/neon-runtime/src/napi/fun.rs index f05ab51b5..297cfb7e3 100644 --- a/crates/neon-runtime/src/napi/fun.rs +++ b/crates/neon-runtime/src/napi/fun.rs @@ -32,7 +32,7 @@ pub unsafe fn call( fun: Local, this: Local, argc: i32, - argv: *mut c_void, + argv: *const c_void, ) -> bool { let status = napi::call_function( env, @@ -51,7 +51,7 @@ pub unsafe fn construct( env: Env, fun: Local, argc: i32, - argv: *mut c_void, + argv: *const c_void, ) -> bool { let status = napi::new_instance(env, fun, argc as usize, argv as *const _, out as *mut _); diff --git a/crates/neon-sys/src/lib.rs b/crates/neon-sys/src/lib.rs index d7910b618..149a83787 100644 --- a/crates/neon-sys/src/lib.rs +++ b/crates/neon-sys/src/lib.rs @@ -206,14 +206,14 @@ extern "C" { fun: Local, this: Local, argc: i32, - argv: *mut c_void, + argv: *const c_void, ) -> bool; pub fn Neon_Fun_Construct( out: &mut Local, isolate: Isolate, fun: Local, argc: i32, - argv: *mut c_void, + argv: *const c_void, ) -> bool; pub fn Neon_Mem_SameHandle(h1: Local, h2: Local) -> bool; diff --git a/src/types/mod.rs b/src/types/mod.rs index d04828af7..20b2c5c4b 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -693,19 +693,19 @@ impl Object for JsFunction {} // Maximum number of function arguments in V8. const V8_ARGC_LIMIT: usize = 65535; -unsafe fn prepare_call<'a, 'b, C: Context<'a>, A>( +fn prepare_call<'a, 'b, C: Context<'a>, A>( cx: &mut C, - args: &mut [Handle<'b, A>], -) -> NeonResult<(i32, *mut c_void)> + args: &[Handle<'b, A>], +) -> NeonResult<(i32, *const c_void)> where A: Value + 'b, { - let argv = args.as_mut_ptr(); + let argv = args.as_ptr(); let argc = args.len(); if argc > V8_ARGC_LIMIT { return cx.throw_range_error("too many arguments"); } - Ok((argc as i32, argv as *mut c_void)) + Ok((argc as i32, argv as *const c_void)) } impl JsFunction { @@ -740,7 +740,7 @@ impl JsFunction { AS: IntoIterator>, { let mut args = args.into_iter().collect::>(); - let (argc, argv) = unsafe { prepare_call(cx, &mut args) }?; + let (argc, argv) = prepare_call(cx, &mut args)?; let env = cx.env().to_raw(); build(cx.env(), |out| unsafe { neon_runtime::fun::call(out, env, self.to_raw(), this.to_raw(), argc, argv) @@ -753,7 +753,7 @@ impl JsFunction { AS: IntoIterator>, { let mut args = args.into_iter().collect::>(); - let (argc, argv) = unsafe { prepare_call(cx, &mut args) }?; + let (argc, argv) = prepare_call(cx, &mut args)?; let env = cx.env().to_raw(); build(cx.env(), |out| unsafe { neon_runtime::fun::construct(out, env, self.to_raw(), argc, argv) From 2313c5753bb1591cdf25c49ef89a982238210584 Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 29 Oct 2021 06:47:46 -0700 Subject: [PATCH 3/8] Abstract calling and constructing into `do_call` and `do_construct` helpers, respectively. --- src/types/mod.rs | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/types/mod.rs b/src/types/mod.rs index 20b2c5c4b..460f1e9f8 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -728,6 +728,36 @@ impl JsFunction { } impl JsFunction { + fn do_call<'a, 'b: 'a, C, T, A>( + self, + cx: &mut C, + this: Handle<'a, T>, + args: &[Handle<'a, A>], + ) -> JsResult<'b, JsValue> + where + C: Context<'b>, + T: Value, + A: Value, + { + let (argc, argv) = prepare_call(cx, args)?; + let env = cx.env().to_raw(); + build(cx.env(), |out| unsafe { + neon_runtime::fun::call(out, env, self.to_raw(), this.to_raw(), argc, argv) + }) + } + + fn do_construct<'a, 'b: 'a, C, A>(self, cx: &mut C, args: &[Handle<'a, A>]) -> JsResult<'b, CL> + where + C: Context<'b>, + A: Value, + { + let (argc, argv) = prepare_call(cx, args)?; + let env = cx.env().to_raw(); + build(cx.env(), |out| unsafe { + neon_runtime::fun::construct(out, env, self.to_raw(), argc, argv) + }) + } + pub fn call<'a, 'b, C: Context<'a>, T, A, AS>( self, cx: &mut C, @@ -739,12 +769,8 @@ impl JsFunction { A: Value + 'b, AS: IntoIterator>, { - let mut args = args.into_iter().collect::>(); - let (argc, argv) = prepare_call(cx, &mut args)?; - let env = cx.env().to_raw(); - build(cx.env(), |out| unsafe { - neon_runtime::fun::call(out, env, self.to_raw(), this.to_raw(), argc, argv) - }) + let args = args.into_iter().collect::>(); + self.do_call(cx, this, &args) } pub fn construct<'a, 'b, C: Context<'a>, A, AS>(self, cx: &mut C, args: AS) -> JsResult<'a, CL> @@ -752,12 +778,8 @@ impl JsFunction { A: Value + 'b, AS: IntoIterator>, { - let mut args = args.into_iter().collect::>(); - let (argc, argv) = prepare_call(cx, &mut args)?; - let env = cx.env().to_raw(); - build(cx.env(), |out| unsafe { - neon_runtime::fun::construct(out, env, self.to_raw(), argc, argv) - }) + let args = args.into_iter().collect::>(); + self.do_construct(cx, &args) } } From 1dc950a47c7c4610a1428de3b1a48ea2ada40c78 Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 29 Oct 2021 07:00:55 -0700 Subject: [PATCH 4/8] Change `call` and `construct` to take new `Arguments` trait instead of `IntoIterator`. --- src/object/class/mod.rs | 6 +++--- src/types/mod.rs | 20 ++++++++++---------- test/napi/src/js/threads.rs | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/object/class/mod.rs b/src/object/class/mod.rs index 8a12b054b..91fcfd514 100644 --- a/src/object/class/mod.rs +++ b/src/object/class/mod.rs @@ -11,6 +11,7 @@ use crate::context::{Context, Lock}; use crate::handle::{Handle, Managed}; use crate::object::{Object, This}; use crate::result::{JsResult, NeonResult, Throw}; +use crate::types::function::Arguments; use crate::types::private::{Callback, ValueInternal}; use crate::types::{build, JsFunction, JsValue, Value}; use neon_runtime; @@ -103,10 +104,9 @@ pub trait Class: Managed + Any { } /// Convenience method for constructing new instances of this class without having to extract the constructor function. - fn new<'a, 'b, C: Context<'a>, A, AS>(cx: &mut C, args: AS) -> JsResult<'a, Self> + fn new<'a, 'b, C: Context<'a>, A>(cx: &mut C, args: A) -> JsResult<'a, Self> where - A: Value + 'b, - AS: IntoIterator>, + A: Arguments<'b>, { let constructor = Self::constructor(cx)?; constructor.construct(cx, args) diff --git a/src/types/mod.rs b/src/types/mod.rs index 460f1e9f8..36bf6c162 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -89,6 +89,9 @@ pub(crate) mod promise; pub(crate) mod private; pub(crate) mod utf8; +pub mod function; + +use self::function::Arguments; use self::private::{Callback, FunctionCallback}; use self::utf8::Utf8; use crate::context::internal::Env; @@ -99,7 +102,6 @@ use crate::object::{Object, This}; use crate::result::{JsResult, JsResultExt, NeonResult, Throw}; use neon_runtime; use neon_runtime::raw; -use smallvec::SmallVec; use std::fmt; use std::fmt::Debug; use std::marker::PhantomData; @@ -758,27 +760,25 @@ impl JsFunction { }) } - pub fn call<'a, 'b, C: Context<'a>, T, A, AS>( + pub fn call<'a, 'b, C: Context<'a>, T, A>( self, cx: &mut C, this: Handle<'b, T>, - args: AS, + args: A, ) -> JsResult<'a, JsValue> where T: Value, - A: Value + 'b, - AS: IntoIterator>, + A: Arguments<'b>, { - let args = args.into_iter().collect::>(); + let args = args.into_args_vec(); self.do_call(cx, this, &args) } - pub fn construct<'a, 'b, C: Context<'a>, A, AS>(self, cx: &mut C, args: AS) -> JsResult<'a, CL> + pub fn construct<'a, 'b, C: Context<'a>, A>(self, cx: &mut C, args: A) -> JsResult<'a, CL> where - A: Value + 'b, - AS: IntoIterator>, + A: Arguments<'b>, { - let args = args.into_iter().collect::>(); + let args = args.into_args_vec(); self.do_construct(cx, &args) } } diff --git a/test/napi/src/js/threads.rs b/test/napi/src/js/threads.rs index 9e3de5702..f18cfa940 100644 --- a/test/napi/src/js/threads.rs +++ b/test/napi/src/js/threads.rs @@ -207,7 +207,7 @@ pub fn channel_join(mut cx: FunctionContext) -> JsResult { get_message .into_inner(&mut cx) - .call::<_, _, JsValue, _>(&mut cx, this, [])? + .call(&mut cx, this, ())? .downcast_or_throw::(&mut cx) .map(|v| v.value(&mut cx)) }) From 70fcb973c12695d8b6a96e58041b18249f151e71 Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 29 Oct 2021 07:13:35 -0700 Subject: [PATCH 5/8] Overload the result type of `call`, and add `exec` for cases where result is ignored. --- src/event/event_handler.rs | 2 +- src/types/mod.rs | 22 +++++++++++++++--- test/dynamic/native/src/js/eventhandler.rs | 6 ++--- test/dynamic/native/src/js/functions.rs | 14 ++++------- test/napi/src/js/functions.rs | 13 ++++------- test/napi/src/js/threads.rs | 27 +++++++++++----------- 6 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/event/event_handler.rs b/src/event/event_handler.rs index cb9e3b120..d7bbd196c 100644 --- a/src/event/event_handler.rs +++ b/src/event/event_handler.rs @@ -48,7 +48,7 @@ impl EventHandler { { self.schedule_with(move |cx, this, callback| { let args = arg_cb(cx); - let _result = callback.call(cx, this, args); + let _result = callback.exec(cx, this, args); }) } diff --git a/src/types/mod.rs b/src/types/mod.rs index 36bf6c162..87b9778be 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -760,18 +760,34 @@ impl JsFunction { }) } - pub fn call<'a, 'b, C: Context<'a>, T, A>( + pub fn call<'a, 'b, V: Value, C: Context<'a>, T, A>( self, cx: &mut C, this: Handle<'b, T>, args: A, - ) -> JsResult<'a, JsValue> + ) -> JsResult<'a, V> where + V: Value, T: Value, A: Arguments<'b>, { let args = args.into_args_vec(); - self.do_call(cx, this, &args) + self.do_call(cx, this, &args)?.downcast_or_throw::(cx) + } + + pub fn exec<'a, 'b, C: Context<'a>, T, A>( + self, + cx: &mut C, + this: Handle<'b, T>, + args: A, + ) -> NeonResult<()> + where + T: Value, + A: Arguments<'b>, + { + let args = args.into_args_vec(); + self.do_call(cx, this, &args)?; + Ok(()) } pub fn construct<'a, 'b, C: Context<'a>, A>(self, cx: &mut C, args: A) -> JsResult<'a, CL> diff --git a/test/dynamic/native/src/js/eventhandler.rs b/test/dynamic/native/src/js/eventhandler.rs index df612a6ae..253a2e5f0 100644 --- a/test/dynamic/native/src/js/eventhandler.rs +++ b/test/dynamic/native/src/js/eventhandler.rs @@ -112,7 +112,7 @@ declare_types! { thread::spawn(move || { cb.schedule_with(move |cx, this, callback| { let args : Vec> = vec![cx.string("number").upcast()]; - let result = callback.call(cx, this, args); + let result = callback.call::(cx, this, args); let cmd = match result { Ok(v) => { if let Ok(number) = v.downcast::() { @@ -127,8 +127,8 @@ declare_types! { }, Err(e) => format!("threw {}", e) }; - let args : Vec> = vec![cx.string(cmd).upcast()]; - let _result = callback.call(cx, this, args); + let cmd = cx.string(cmd); + let _result = callback.exec(cx, this, [cmd]); }); }); } diff --git a/test/dynamic/native/src/js/functions.rs b/test/dynamic/native/src/js/functions.rs index cafc80715..630f8114c 100644 --- a/test/dynamic/native/src/js/functions.rs +++ b/test/dynamic/native/src/js/functions.rs @@ -13,26 +13,20 @@ pub fn return_js_function(mut cx: FunctionContext) -> JsResult { pub fn call_js_function(mut cx: FunctionContext) -> JsResult { let f = cx.argument::(0)?; - let args: Vec> = vec![cx.number(16.0)]; + let arg = cx.number(16.0); let null = cx.null(); - f.call(&mut cx, null, args)? - .downcast::() - .or_throw(&mut cx) + f.call::(&mut cx, null, [arg]) } pub fn construct_js_function(mut cx: FunctionContext) -> JsResult { let f = cx.argument::(0)?; let zero = cx.number(0.0); - let o = f.construct(&mut cx, vec![zero])?; + let o = f.construct(&mut cx, [zero])?; let get_utc_full_year_method = o .get(&mut cx, "getUTCFullYear")? .downcast::() .or_throw(&mut cx)?; - let args: Vec> = vec![]; - get_utc_full_year_method - .call(&mut cx, o.upcast::(), args)? - .downcast::() - .or_throw(&mut cx) + get_utc_full_year_method.call::(&mut cx, o, ()) } trait CheckArgument<'a> { diff --git a/test/napi/src/js/functions.rs b/test/napi/src/js/functions.rs index 5a8bd819c..f0cf211e0 100644 --- a/test/napi/src/js/functions.rs +++ b/test/napi/src/js/functions.rs @@ -12,26 +12,21 @@ pub fn return_js_function(mut cx: FunctionContext) -> JsResult { pub fn call_js_function(mut cx: FunctionContext) -> JsResult { let f = cx.argument::(0)?; - let args: Vec> = vec![cx.number(16.0)]; + let arg = cx.number(16.0); let null = cx.null(); - f.call(&mut cx, null, args)? - .downcast::(&mut cx) - .or_throw(&mut cx) + f.call::(&mut cx, null, [arg]) } pub fn construct_js_function(mut cx: FunctionContext) -> JsResult { let f = cx.argument::(0)?; let zero = cx.number(0.0); - let o = f.construct(&mut cx, vec![zero])?; + let o = f.construct(&mut cx, [zero])?; let get_utc_full_year_method = o .get(&mut cx, "getUTCFullYear")? .downcast::(&mut cx) .or_throw(&mut cx)?; let args: Vec> = vec![]; - get_utc_full_year_method - .call(&mut cx, o.upcast::(), args)? - .downcast::(&mut cx) - .or_throw(&mut cx) + get_utc_full_year_method.call::(&mut cx, o, ()) } trait CheckArgument<'a> { diff --git a/test/napi/src/js/threads.rs b/test/napi/src/js/threads.rs index f18cfa940..e9edc76bf 100644 --- a/test/napi/src/js/threads.rs +++ b/test/napi/src/js/threads.rs @@ -21,9 +21,8 @@ pub fn thread_callback(mut cx: FunctionContext) -> JsResult { channel.send(move |mut cx| { let callback = callback.into_inner(&mut cx); let this = cx.undefined(); - let args = Vec::>::new(); - callback.call(&mut cx, this, args)?; + callback.exec(&mut cx, this, ())?; Ok(()) }) @@ -45,9 +44,9 @@ pub fn multi_threaded_callback(mut cx: FunctionContext) -> JsResult channel.send(move |mut cx| { let callback = callback.into_inner(&mut cx); let this = cx.undefined(); - let args = vec![cx.number(i as f64)]; + let i = cx.number(i as f64); - callback.call(&mut cx, this, args)?; + callback.exec(&mut cx, this, [i])?; Ok(()) }) @@ -78,9 +77,9 @@ impl AsyncGreeter { channel.send(|mut cx| { let callback = callback.into_inner(&mut cx); let this = cx.undefined(); - let args = vec![cx.string(greeting)]; + let greeting = cx.string(greeting); - callback.call(&mut cx, this, args)?; + callback.exec(&mut cx, this, [greeting])?; Ok(()) }) @@ -99,8 +98,7 @@ impl Finalize for AsyncGreeter { if let Some(shutdown) = shutdown { let shutdown = shutdown.into_inner(cx); let this = cx.undefined(); - let args = Vec::>::new(); - let _ = shutdown.call(cx, this, args); + let _ = shutdown.exec(cx, this, ()); } callback.drop(cx); @@ -163,9 +161,9 @@ pub fn drop_global_queue(mut cx: FunctionContext) -> JsResult { self.channel.send(|mut cx| { let callback = callback.into_inner(&mut cx); let this = cx.undefined(); - let args = vec![cx.undefined()]; + let undefined = cx.undefined(); - callback.call(&mut cx, this, args)?; + callback.exec(&mut cx, this, [undefined])?; Ok(()) }); @@ -207,8 +205,7 @@ pub fn channel_join(mut cx: FunctionContext) -> JsResult { get_message .into_inner(&mut cx) - .call(&mut cx, this, ())? - .downcast_or_throw::(&mut cx) + .call::(&mut cx, this, ()) .map(|v| v.value(&mut cx)) }) .join() @@ -220,9 +217,11 @@ pub fn channel_join(mut cx: FunctionContext) -> JsResult { // Call back to JavaScript with the response channel.send(move |mut cx| { let this = cx.undefined(); - let args = [cx.string(response)]; + let response = cx.string(response); - callback.into_inner(&mut cx).call(&mut cx, this, args)?; + callback + .into_inner(&mut cx) + .exec(&mut cx, this, [response])?; Ok(()) }); From f83c23b09660858ad354928cfe47b17f852e32db Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 29 Oct 2021 09:33:42 -0700 Subject: [PATCH 6/8] Add missing `neon::types::function` modules. --- src/types/function/mod.rs | 140 ++++++++++++++++++++++++++++++++++ src/types/function/private.rs | 11 +++ 2 files changed, 151 insertions(+) create mode 100644 src/types/function/mod.rs create mode 100644 src/types/function/private.rs diff --git a/src/types/function/mod.rs b/src/types/function/mod.rs new file mode 100644 index 000000000..1a4e9b605 --- /dev/null +++ b/src/types/function/mod.rs @@ -0,0 +1,140 @@ +//! Types and traits for working with JavaScript functions. + +use crate::handle::Handle; +use crate::types::Value; + +use smallvec::smallvec; + +pub(crate) mod private; + +/// The trait for specifying arguments for a function call. This trait is sealed and cannot +/// be implemented by types outside of the Neon crate. +/// +/// **Note:** This trait is implemented for tuples of up to 32 JavaScript values, +/// but for the sake of brevity, only tuples up to size 8 are shown in this documentation. +pub trait Arguments<'a>: private::ArgumentsInternal<'a> {} + +impl<'a, T: Value> private::ArgumentsInternal<'a> for Vec> { + fn into_args_vec(self) -> private::ArgsVec<'a> { + let mut args = smallvec![]; + for arg in self { + args.push(arg.upcast()); + } + args + } +} + +impl<'a, T: Value> Arguments<'a> for Vec> {} + +impl<'a, T: Value, const N: usize> private::ArgumentsInternal<'a> for [Handle<'a, T>; N] { + fn into_args_vec(self) -> private::ArgsVec<'a> { + let mut args = smallvec![]; + for arg in self { + args.push(arg.upcast()); + } + args + } +} + +impl<'a, T: Value, const N: usize> Arguments<'a> for [Handle<'a, T>; N] {} + +impl<'a> private::ArgumentsInternal<'a> for () { + fn into_args_vec(self) -> private::ArgsVec<'a> { + smallvec![] + } +} + +impl<'a> Arguments<'a> for () {} + +macro_rules! impl_arguments { + { + [ $(($tprefix:ident, $vprefix:ident), )* ]; + []; + } => {}; + + { + [ $(($tprefix:ident, $vprefix:ident), )* ]; + [ $(#[$attr1:meta])? ($tname1:ident, $vname1:ident), $($(#[$attrs:meta])? ($tnames:ident, $vnames:ident), )* ]; + } => { + $(#[$attr1])? + impl<'a, $($tprefix: Value, )* $tname1: Value> private::ArgumentsInternal<'a> for ($(Handle<'a, $tprefix>, )* Handle<'a, $tname1>, ) { + fn into_args_vec(self) -> private::ArgsVec<'a> { + let mut args = smallvec![]; + let ($($vprefix, )* $vname1, ) = self; + $(args.push($vprefix.upcast());)* + args.push($vname1.upcast()); + args + } + } + + $(#[$attr1])? + impl<'a, $($tprefix: Value, )* $tname1: Value> Arguments<'a> for ($(Handle<'a, $tprefix>, )* Handle<'a, $tname1>, ) {} + + impl_arguments! { + [ $(($tprefix, $vprefix), )* ($tname1, $vname1), ]; + [ $($(#[$attrs])? ($tnames, $vnames), )* ]; + } + }; +} + +impl_arguments! { + []; + [ + (V1, v1), + (V2, v2), + (V3, v3), + (V4, v4), + (V5, v5), + (V6, v6), + (V7, v7), + (V8, v8), + #[doc(hidden)] + (V9, v9), + #[doc(hidden)] + (V10, v10), + #[doc(hidden)] + (V11, v11), + #[doc(hidden)] + (V12, v12), + #[doc(hidden)] + (V13, v13), + #[doc(hidden)] + (V14, v14), + #[doc(hidden)] + (V15, v15), + #[doc(hidden)] + (V16, v16), + #[doc(hidden)] + (V17, v17), + #[doc(hidden)] + (V18, v18), + #[doc(hidden)] + (V19, v19), + #[doc(hidden)] + (V20, v20), + #[doc(hidden)] + (V21, v21), + #[doc(hidden)] + (V22, v22), + #[doc(hidden)] + (V23, v23), + #[doc(hidden)] + (V24, v24), + #[doc(hidden)] + (V25, v25), + #[doc(hidden)] + (V26, v26), + #[doc(hidden)] + (V27, v27), + #[doc(hidden)] + (V28, v28), + #[doc(hidden)] + (V29, v29), + #[doc(hidden)] + (V30, v30), + #[doc(hidden)] + (V31, v31), + #[doc(hidden)] + (V32, v32), + ]; +} diff --git a/src/types/function/private.rs b/src/types/function/private.rs new file mode 100644 index 000000000..e58d328fa --- /dev/null +++ b/src/types/function/private.rs @@ -0,0 +1,11 @@ +use crate::handle::Handle; +use crate::types::JsValue; + +use smallvec::SmallVec; + +pub type ArgsVec<'a> = SmallVec<[Handle<'a, JsValue>; 8]>; + +/// This type marks the `Arguments` trait as sealed. +pub trait ArgumentsInternal<'a> { + fn into_args_vec(self) -> ArgsVec<'a>; +} From 39c99029bdd5fed7754b491875b25834a469bfdc Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 29 Oct 2021 11:13:28 -0700 Subject: [PATCH 7/8] Fix doc tests. --- src/context/mod.rs | 5 ++--- src/types/boxed.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/context/mod.rs b/src/context/mod.rs index e9c405864..3601d0f4b 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -94,9 +94,8 @@ //! //! while !done { //! done = cx.execute_scoped(|mut cx| { // temporary scope -//! let args: Vec> = vec![]; -//! let obj = next.call(&mut cx, iterator, args)? // temporary object -//! .downcast_or_throw::(&mut cx)?; +//! let obj: Handle = next // temporary object +//! .call(&mut cx, iterator, ())?; //! let number = obj.get(&mut cx, "value")? // temporary number //! .downcast_or_throw::(&mut cx)? //! .value(&mut cx); diff --git a/src/types/boxed.rs b/src/types/boxed.rs index 867e81157..f4378039f 100644 --- a/src/types/boxed.rs +++ b/src/types/boxed.rs @@ -294,7 +294,7 @@ impl<'a, T: Send + 'static> Deref for JsBox { /// cx.number(self.1).upcast(), /// ]; /// -/// emit.call(cx, global, args).unwrap(); +/// emit.exec(cx, global, args).unwrap(); /// } /// } /// ``` From 900ab602cbaed70bcc17e8366485038e80782148 Mon Sep 17 00:00:00 2001 From: David Herman Date: Fri, 29 Oct 2021 11:20:14 -0700 Subject: [PATCH 8/8] Removed unused variable in test. --- test/napi/src/js/functions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/napi/src/js/functions.rs b/test/napi/src/js/functions.rs index f0cf211e0..20728f94b 100644 --- a/test/napi/src/js/functions.rs +++ b/test/napi/src/js/functions.rs @@ -25,7 +25,6 @@ pub fn construct_js_function(mut cx: FunctionContext) -> JsResult { .get(&mut cx, "getUTCFullYear")? .downcast::(&mut cx) .or_throw(&mut cx)?; - let args: Vec> = vec![]; get_utc_full_year_method.call::(&mut cx, o, ()) }