Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added functionality to allow returning wrapped classes from member functions #13

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
35 changes: 28 additions & 7 deletions src/vu8/Class.hpp
Expand Up @@ -9,12 +9,15 @@
#include <vu8/detail/Proto.hpp>
#include <vu8/detail/Singleton.hpp>
#include <vu8/detail/Class.hpp>
#include <vu8/detail/TypeTraits.hpp>

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/adapted/mpl.hpp>
#include <boost/fusion/include/push_front.hpp>
#include <boost/fusion/include/join.hpp>

#include <boost/type_traits/is_void.hpp>

#include <iostream>
#include <stdexcept>

Expand Down Expand Up @@ -64,7 +67,7 @@ struct ClassSingletonFactory<M, NoFactory> {

template <class T, class Factory>
class ClassSingleton
: detail::LazySingleton< ClassSingleton<T, Factory> >,
: private detail::LazySingleton< ClassSingleton<T, Factory> >,
public ClassSingletonFactory<ClassSingleton<T, Factory>, Factory>
{
friend class ClassSingletonFactory<ClassSingleton<T, Factory>, Factory>;
Expand Down Expand Up @@ -96,20 +99,38 @@ class ClassSingleton
}

template <class P>
static inline typename boost::disable_if<
boost::is_same<void, typename P::return_type>, ValueHandle >::type
ForwardReturn(T *obj, const v8::Arguments& args) {
static inline typename
boost::enable_if<vu8::is_to_v8_convertible<typename P::return_type>,
ValueHandle >::type ForwardReturn (T *obj, const v8::Arguments& args) {
return ToV8(Invoke<P>(obj, args));
}

template <class P>
static inline typename boost::enable_if<
boost::is_same<void, typename P::return_type>, ValueHandle >::type
ForwardReturn(T *obj, const v8::Arguments& args) {
static inline typename
boost::enable_if<boost::is_void<typename P::return_type>,
ValueHandle >::type ForwardReturn (T *obj, const v8::Arguments& args) {
Invoke<P>(obj, args);
return v8::Undefined();
}

template <class P>
static inline typename
boost::enable_if<typename P::IS_RETURN_WRAPPED_CLASS,
ValueHandle >::type ForwardReturn (T *obj, const v8::Arguments& args) {
typedef typename P::ClassSingleton LocalSelf;
typedef typename P::return_type ReturnType;

v8::HandleScope scope;
ReturnType* return_value = new ReturnType(Invoke<P>(obj, args));
v8::Local<v8::Object> localObj =
LocalSelf::Instance().func_->GetFunction()->NewInstance();
v8::Persistent<v8::Object> persistentObj =
v8::Persistent<v8::Object>::New(localObj);
persistentObj->SetInternalField(0, v8::External::New(return_value));
persistentObj.MakeWeak(return_value, &LocalSelf::MadeWeak);
return scope.Close(localObj);
}

// every method is run inside a handle scope
template <class P>
static inline ValueHandle Forward(const v8::Arguments& args) {
Expand Down
26 changes: 25 additions & 1 deletion src/vu8/detail/ProtoHelper.hpp
Expand Up @@ -7,11 +7,17 @@
# include <boost/preprocessor/punctuation/comma_if.hpp>
# include <boost/preprocessor/iteration/iterate.hpp>
# include <boost/mpl/vector.hpp>
# include <boost/type_traits/integral_constant.hpp>

# ifndef VU8_PROTO_MAX_SIZE
# define VU8_PROTO_MAX_SIZE VU8_PP_ITERATION_LIMIT
# endif
namespace vu8 { namespace detail {
namespace vu8 {

template <class T, class F> struct Class;
template <class T, class F> struct ClassSingleton;

namespace detail {

namespace mpl = boost::mpl;

Expand Down Expand Up @@ -48,12 +54,30 @@ template <class C, class R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A)
struct MemFunProto<C, R ( BOOST_PP_ENUM_PARAMS(n, A) )> : FunProtoBase<R> {
typedef mpl::vector<BOOST_PP_ENUM_PARAMS(n, A)> arguments;
typedef R(C::*method_type)(BOOST_PP_ENUM_PARAMS(n, A));
typedef boost::false_type IS_RETURN_WRAPPED_CLASS;
};

template <class C, class R, class Factory BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A)>
struct MemFunProto<C, vu8::Class<R, Factory> ( BOOST_PP_ENUM_PARAMS(n, A) )> : FunProtoBase<R> {
typedef mpl::vector<BOOST_PP_ENUM_PARAMS(n, A)> arguments;
typedef R(C::*method_type)(BOOST_PP_ENUM_PARAMS(n, A));
typedef boost::true_type IS_RETURN_WRAPPED_CLASS;
typedef vu8::ClassSingleton<R, Factory> ClassSingleton;
};

template <class C, class R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A)>
struct MemFunProto<C const, R ( BOOST_PP_ENUM_PARAMS(n, A) )> : FunProtoBase<R> {
typedef mpl::vector<BOOST_PP_ENUM_PARAMS(n, A)> arguments;
typedef R(C::*method_type)(BOOST_PP_ENUM_PARAMS(n, A)) const;
typedef boost::false_type IS_RETURN_WRAPPED_CLASS;
};

template <class C, class R, class Factory BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A)>
struct MemFunProto<C const, vu8::Class<R, Factory> ( BOOST_PP_ENUM_PARAMS(n, A) )> : FunProtoBase<R> {
typedef mpl::vector<BOOST_PP_ENUM_PARAMS(n, A)> arguments;
typedef R(C::*method_type)(BOOST_PP_ENUM_PARAMS(n, A)) const;
typedef boost::true_type IS_RETURN_WRAPPED_CLASS;
typedef vu8::ClassSingleton<R, Factory> ClassSingleton;
};

} }
Expand Down
43 changes: 43 additions & 0 deletions src/vu8/detail/TypeTraits.hpp
@@ -0,0 +1,43 @@
#ifndef TYPETRAITS_HPP_
#define TYPETRAITS_HPP_

#include <string>

#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>

#include <boost/utility/enable_if.hpp>

#include <v8.h>

namespace vu8 {

template <class T> struct remove_reference_and_const {
typedef typename boost::remove_const<
typename boost::remove_reference<T>::type
>::type type;
};

template <class T, class Enable = void>
struct is_to_v8_convertible : public boost::false_type { };

template <class T>
struct is_to_v8_convertible<T, typename boost::enable_if<
boost::is_arithmetic<T>
>::type> : public boost::true_type { };

#define VU8_TO_V8_CONV_TYPE_TRAIT_SPEC(T,M,spec) \
template <class T > \
struct is_to_v8_convertible<T, typename boost::enable_if< \
boost::is_same<M, spec > \
>::type> : public boost::true_type { }; \
/**/

VU8_TO_V8_CONV_TYPE_TRAIT_SPEC(T,T,v8::Handle<v8::Value>);
VU8_TO_V8_CONV_TYPE_TRAIT_SPEC(T,typename remove_reference_and_const<T>::type, std::string);
}

#endif /* TYPETRAITS_HPP_ */