diff --git a/v8pp/convert.hpp b/v8pp/convert.hpp index 140023aa..54e1a008 100644 --- a/v8pp/convert.hpp +++ b/v8pp/convert.hpp @@ -427,6 +427,85 @@ struct convert::val } }; +template +v8::Local call_v8(v8::Isolate* isolate, v8::Local func, + v8::Local recv, Args&&... args); + +template +v8::Local wrap_function(v8::Isolate* isolate, string_view name, F&& func); + +namespace detail { + +template +struct function_from_v8_helper +{ + function_from_v8_helper(v8::Isolate* isolate, std::shared_ptr> function) + : isolate_(isolate) + , function_(std::move(function)) + { + } + + R operator()( Args... args ) + { + v8::Local ret = call_v8(isolate_, function_->Get(isolate_), v8::Undefined(isolate_), std::forward(args)...); + return convert::from_v8(ret); + } + +private: + v8::Isolate* isolate_; + std::shared_ptr> function_; +}; + +template +struct function_from_v8_helper +{ + function_from_v8_helper(v8::Isolate* isolate, std::shared_ptr> function) + : isolate_(isolate) + , function_(std::move(function)) + { + } + + void operator()( Args... args ) + { + call_v8(isolate_, function_->Get(isolate_), v8::Undefined(isolate_), std::forward(args)...); + } + +private: + v8::Isolate* isolate_; + std::shared_ptr> function_; +}; + +} // namespace detail + +template +struct convert> +{ + using from_type = std::function; + using to_type = v8::Local; + + static bool is_valid(v8::Isolate*, v8::Local value) + { + return !value.IsEmpty() && value->IsFunction(); + } + + static from_type from_v8(v8::Isolate* isolate, v8::Local value) + { + if (!is_valid(isolate, value)) + { + throw invalid_argument(isolate, value, "Function"); + } + + v8::HandleScope scope(isolate); + v8::Global function(isolate, value.As()); + return from_type( detail::function_from_v8_helper(isolate, std::make_shared>( function.Pass() )) ); + } + + static to_type to_v8(v8::Isolate* isolate, from_type&& value) + { + return wrap_function(isolate, "", std::forward(value)); + } +}; + template struct convert> { @@ -458,7 +537,8 @@ struct is_wrapped_class : conjunction< negation>, negation>, negation>, - negation> + negation>, + negation> > {}; // convert specialization for wrapped user classes diff --git a/v8pp/utility.hpp b/v8pp/utility.hpp index 1082fbc7..c0e30611 100644 --- a/v8pp/utility.hpp +++ b/v8pp/utility.hpp @@ -281,6 +281,16 @@ struct is_shared_ptr : std::false_type {}; template struct is_shared_ptr> : std::true_type {}; +///////////////////////////////////////////////////////////////////////////// +// +// is_function +// +template +struct is_function : std::false_type {}; + +template +struct is_function> : std::true_type {}; + ///////////////////////////////////////////////////////////////////////////// // // Function traits