Skip to content

Commit

Permalink
convert return value of wrapped C++ function with respect to class pt…
Browse files Browse the repository at this point in the history
…r_traits

A wrapped function may return a wrapped C++ object, so we need to use
appropriate converter specialization (e.g. `convert<std::shared_ptr<T>`) for
such a wrapped class `T`.

Reusing `call_from_v8_traits<F>::arg_converter<return_type, Traits>` meta-function
to get the converter type in `forward_ret()` for the certain function result type.

Extracted `call_from_v8_traits<F>::arg_converter<Arg, Traits>` to use a type
instead of argument index.

Added optional `Traits = raw_ptr_traits` template argument to `wrap_function()`
and `wrap_function_template()` in order to allow `forward_function()`
instantiation for the specified `Traits`

Work in context of issue #113
  • Loading branch information
pmed committed Jul 21, 2019
1 parent 6af1f0f commit d7ed5a3
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 12 deletions.
15 changes: 9 additions & 6 deletions v8pp/call_from_v8.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,11 @@ struct call_from_v8_traits
using type = void;
};

template<size_t Index>
using arg_type = typename tuple_element<Index + is_mem_fun,
Index < (arg_count + Offset)>::type;

template<size_t Index, typename Traits, typename Arg = arg_type<Index>,
template<typename Arg, typename Traits,
typename T = typename std::remove_reference<Arg>::type,
typename U = typename std::remove_pointer<T>::type
>
using arg_convert = typename std::conditional<
using arg_converter = typename std::conditional<
is_wrapped_class<typename std::remove_cv<U>::type>::value,
typename std::conditional<
std::is_pointer<T>::value,
Expand All @@ -57,6 +53,13 @@ struct call_from_v8_traits
convert<typename std::remove_cv<T>::type>
>::type;

template<size_t Index>
using arg_type = typename tuple_element<Index + is_mem_fun,
Index < (arg_count + Offset)>::type;

template<size_t Index, typename Traits>
using arg_convert = arg_converter<arg_type<Index>, Traits>;

template<size_t Index, typename Traits>
static decltype(arg_convert<Index, Traits>::from_v8(std::declval<v8::Isolate*>(), std::declval<v8::Local<v8::Value>>()))
arg_from_v8(v8::FunctionCallbackInfo<v8::Value> const& args)
Expand Down
14 changes: 8 additions & 6 deletions v8pp/function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ void forward_ret(v8::FunctionCallbackInfo<v8::Value> const& args, std::true_type
template<typename Traits, typename F>
void forward_ret(v8::FunctionCallbackInfo<v8::Value> const& args, std::false_type /*is_void_return*/)
{
args.GetReturnValue().Set(to_v8(args.GetIsolate(),
using return_type = typename function_traits<F>::return_type;
using converter = call_from_v8_traits<F>::arg_converter<return_type, Traits>;
args.GetReturnValue().Set(converter::to_v8(args.GetIsolate(),
invoke<Traits, F>(args, std::is_member_function_pointer<F>())));
}

Expand All @@ -179,25 +181,25 @@ void forward_function(v8::FunctionCallbackInfo<v8::Value> const& args)
} // namespace detail

/// Wrap C++ function into new V8 function template
template<typename F>
template<typename F, typename Traits = raw_ptr_traits>
v8::Local<v8::FunctionTemplate> wrap_function_template(v8::Isolate* isolate, F&& func)
{
using F_type = typename std::decay<F>::type;
return v8::FunctionTemplate::New(isolate,
&detail::forward_function<raw_ptr_traits, F_type>,
&detail::forward_function<Traits, F_type>,
detail::set_external_data(isolate, std::forward<F_type>(func)));
}

/// Wrap C++ function into new V8 function
/// Set nullptr or empty string for name
/// to make the function anonymous
template<typename F>
template<typename F, typename Traits = raw_ptr_traits>
v8::Local<v8::Function> wrap_function(v8::Isolate* isolate,
char const* name, F&& func)
char const* name, F && func)
{
using F_type = typename std::decay<F>::type;
v8::Local<v8::Function> fn = v8::Function::New(isolate->GetCurrentContext(),
&detail::forward_function<raw_ptr_traits, F_type>,
&detail::forward_function<Traits, F_type>,
detail::set_external_data(isolate, std::forward<F_type>(func))).ToLocalChecked();
if (name && *name)
{
Expand Down

0 comments on commit d7ed5a3

Please sign in to comment.