Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include "Utils/TypeTraitsExt.h"
- namespace JS
- {
- class Scope;
- namespace detail
- {
- void registerClassTemplate(const std::wstring& clsName, std::shared_ptr<Scope> parent, v8::Persistent<v8::FunctionTemplate> constructor);
- };
- template<typename T>
- class Class : public std::enable_shared_from_this<Class<T>>
- {
- friend class Namespace;
- template<typename Q>
- class ClassInstance
- {
- std::shared_ptr<Q> mInstance;
- public:
- ClassInstance(std::shared_ptr<Q> instance) : mInstance(instance) {
- }
- std::shared_ptr<Q> getInstance() { return mInstance; }
- };
- template<typename Res, typename... OArgs>
- class FunctionInstance
- {
- private:
- std::function<Res (OArgs...)> mFunction;
- template<uint32 size, typename _T, typename... FullArgs, typename... Args>
- Res expand(std::shared_ptr<T> instance, const v8::Arguments& args, Args... curArgs) {
- return expand<size + 1, FullArgs...>(instance, args, curArgs..., getParam<_T>(args[size]));
- }
- template<uint32 size, typename... Args>
- Res expand(std::shared_ptr<T> instance, const v8::Arguments& args, Args... curArgs) {
- return mFunction(instance.get(), curArgs...);
- }
- template<uint32 size, typename _T, typename... FullArgs, typename... Args>
- Res expandUnbound(std::shared_ptr<T> instance, const v8::Arguments& args, Args... curArgs) {
- return expandUnbound<size + 1, FullArgs...>(instance, args, curArgs..., getParam<_T>(args[size]));
- }
- template<uint32 size, typename... Args>
- Res expandUnbound(std::shared_ptr<T> instance, const v8::Arguments& args, Args... curArgs) {
- return mFunction(instance, curArgs...);
- }
- template<uint32 size, typename _T, typename... Args>
- typename Utils::enable_if_not<Utils::IsSharedPtr<_T>::value, Res>::type expandMember(std::shared_ptr<T> instance, const v8::Arguments& args) {
- return expand<0, Args...>(instance, args);
- }
- template<uint32 size, typename _T, typename... Args>
- typename std::enable_if<Utils::IsSharedPtr<_T>::value, Res>::type expandMember(std::shared_ptr<T> instance, const v8::Arguments& args) {
- return expandUnbound<0, Args...>(instance, args);
- }
- public:
- FunctionInstance(std::function<Res (OArgs...)> fun) : mFunction(fun) {
- }
- Res callFunction(std::shared_ptr<T> instance, const v8::Arguments& args) {
- return expandMember<0, OArgs...>(instance, args);
- }
- };
- template<typename Res, typename... Args>
- static v8::Handle<v8::Value> __cdecl memberFunctionCallback(const v8::Arguments& args) {
- FunctionInstance<Res, Args...>* fPtr = (FunctionInstance<Res, Args...>*)v8::Local<v8::External>::Cast(args.Data())->Value();
- ClassInstance<T>* inst = (ClassInstance<T>*)v8::Local<v8::External>::Cast(args.This()->GetInternalField(0))->Value();
- Res res = fPtr->callFunction(inst->getInstance(), args);
- return pushParam<Res>(res);
- }
- static void __cdecl destructorCall(v8::Persistent<v8::Value> obj, void* params) {
- ClassInstance<T>* instance = (ClassInstance<T>*)params;
- delete instance;
- obj.Dispose();
- }
- template<typename... Args>
- static v8::Handle<v8::Value> __cdecl constructorCall(const v8::Arguments& args) {
- if(!args.IsConstructCall())
- return v8::Undefined();
- Class<T>* cls = (Class<T>*)v8::Local<v8::External>::Cast(args.Data())->Value();
- ClassInstance<T>* instance = new ClassInstance<T>(cls->expand<0, Args...>(args));
- auto obj = v8::Persistent<v8::Object>::New(cls->mPrototype->NewInstance());
- obj->SetInternalField(0, v8::External::New(instance));
- obj.MakeWeak(instance, &Class<T>::destructorCall);
- return obj;
- }
- template<typename P>
- static void __cdecl defPropertySetCall(v8::Local<v8::String> key, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {
- ClassInstance<T>* inst = (ClassInstance<T>*)v8::Local<v8::External>::Cast(info.This()->GetInternalField(0))->Value();
- P T::*memPtr = union_cast<P T::*>(v8::Local<v8::External>::Cast(info.Data())->Value());
- inst->getInstance().get()->*memPtr = getParam<P>(value);
- }
- template<typename P>
- static v8::Handle<v8::Value> __cdecl defPropertyGetCall(v8::Local<v8::String> key, const v8::AccessorInfo& info) {
- ClassInstance<T>* inst = (ClassInstance<T>*)v8::Local<v8::External>::Cast(info.This()->GetInternalField(0))->Value();
- P T::*memPtr = union_cast<P T::*>(v8::Local<v8::External>::Cast(info.Data())->Value());
- const P& value = inst->getInstance().get()->*memPtr;
- return pushParam<P>(value);
- }
- template<typename T>
- static typename std::enable_if<std::is_integral<T>::value, v8::Handle<v8::Value>>::type pushParam(const T& value) {
- return v8::Integer::New((int32_t)value);
- }
- template<typename T>
- static typename std::enable_if<std::is_floating_point<T>::value, v8::Handle<v8::Value>>::type pushParam(const T& value) {
- return v8::Number::New((double)value);
- }
- template<typename T>
- static typename std::enable_if<std::is_integral<T>::value, T>::type getParam(v8::Handle<v8::Value> val) {
- return (T)val->IntegerValue();
- }
- template<typename T>
- static typename std::enable_if<std::is_floating_point<T>::value, T>::type getParam(v8::Handle<v8::Value> val) {
- return (T)val->NumberValue();
- }
- template<uint32 size, typename _T, typename... FullArgs, typename... Args>
- std::shared_ptr<T> expand(const v8::Arguments& args, Args... curArgs) {
- return expand<size + 1, FullArgs...>(args, curArgs..., getParam<_T>(args[size]));
- }
- template<uint32 size, typename... Args>
- std::shared_ptr<T> expand(const v8::Arguments& args, Args... curArgs) {
- return std::make_shared<T>(curArgs...);
- }
- template<typename... Args>
- std::shared_ptr<T> callFunction(const v8::Arguments& args) {
- return expand<0, Args...>(args);
- }
- v8::Persistent<v8::ObjectTemplate> mPrototype;
- v8::Persistent<v8::FunctionTemplate> mConstructorObj;
- std::wstring mName;
- std::shared_ptr<Scope> mParent;
- std::shared_ptr<Class<T>> mOwnHolder;
- void keepAlive() {
- mOwnHolder = shared_from_this();
- }
- template<typename Dst, typename Src>
- static Dst union_cast(Src src) {
- union { Src s; Dst d; } u = { src };
- return u.d;
- }
- public:
- Class(const std::wstring& name, std::shared_ptr<Scope> parent) {
- mName = name;
- mParent = parent;
- }
- template<typename Res, typename... Args>
- void def_function(const std::wstring& name, Res (T::*func)(Args...)) {
- v8::Persistent<v8::External> pers = v8::Persistent<v8::External>::New(v8::External::New(new FunctionInstance<Res, T*, Args...>(std::mem_fun<Res, T, Args...>(func))));
- v8::Persistent<v8::FunctionTemplate> funTmpl = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(&Class<T>::memberFunctionCallback<Res, T*, Args...>, pers));
- mPrototype->Set(v8::String::New(StringUtils::toAnsi(name).c_str()), funTmpl);
- }
- template<typename Res, typename... Args>
- void def_function(const std::wstring& name, std::function<Res (std::shared_ptr<T>, Args...)> fun) {
- v8::Persistent<v8::External> pers = v8::Persistent<v8::External>::New(v8::External::New(new FunctionInstance<Res, std::shared_ptr<T>, Args...>(fun)));
- v8::Persistent<v8::FunctionTemplate> funTmpl = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(&Class<T>::memberFunctionCallback<Res, std::shared_ptr<T>, Args...>, pers));
- mPrototype->Set(v8::String::New(StringUtils::toAnsi(name).c_str()), funTmpl);
- }
- template<typename Res, typename... Args>
- void def_function(const std::wstring& name, Res (*fun)(std::shared_ptr<T>, Args...)) {
- def_function(name, std::function<Res (std::shared_ptr<T>, Args...)>(fun));
- }
- template<typename... Args>
- void def_constructor() {
- mConstructorObj = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(&Class<T>::constructorCall<Args...>, v8::External::New(this)));
- mPrototype = v8::Persistent<v8::ObjectTemplate>::New(mConstructorObj->PrototypeTemplate());
- mPrototype->SetInternalFieldCount(1);
- }
- template<typename P>
- void def_property(const std::wstring& name, P T::* ptr) {
- mPrototype->SetAccessor(
- v8::String::New(StringUtils::toAnsi(name).c_str()),
- &Class<T>::defPropertyGetCall<P>,
- &Class<T>::defPropertySetCall<P>,
- v8::External::New(union_cast<void*>(ptr)));
- }
- void finalize() {
- detail::registerClassTemplate(mName, mParent, mConstructorObj);
- }
- };
- };
Advertisement
Add Comment
Please, Sign In to add comment