Add ES5 classes
This commit is contained in:
parent
bb46894d97
commit
98aaf2d4ba
|
@ -1,7 +1,7 @@
|
|||
#ifndef _ADDON_TOOLS_HPP_
|
||||
#define _ADDON_TOOLS_HPP_
|
||||
|
||||
|
||||
#define NODE_ADDON_API_DISABLE_DEPRECATED
|
||||
#include <napi.h>
|
||||
|
||||
|
||||
|
@ -479,5 +479,157 @@ inline void eventEmitAsync(
|
|||
|
||||
}
|
||||
|
||||
inline void inheritEs5(napi_env env, Napi::Function ctor, Napi::Function superCtor) {
|
||||
napi_value global, globalObject, setProto, ctorProtoProp, superCtorProtoProp;
|
||||
napi_value argv[2];
|
||||
|
||||
napi_get_global(env, &global);
|
||||
napi_get_named_property(env, global, "Object", &globalObject);
|
||||
napi_get_named_property(env, globalObject, "setPrototypeOf", &setProto);
|
||||
napi_get_named_property(env, ctor, "prototype", &ctorProtoProp);
|
||||
napi_get_named_property(env, superCtor, "prototype", &superCtorProtoProp);
|
||||
|
||||
argv[0] = ctorProtoProp;
|
||||
argv[1] = superCtorProtoProp;
|
||||
napi_call_function(env, global, setProto, 2, argv, nullptr);
|
||||
|
||||
argv[0] = ctor;
|
||||
argv[1] = superCtor;
|
||||
napi_call_function(env, global, setProto, 2, argv, nullptr);
|
||||
|
||||
ctor.Set("super_", superCtor); \
|
||||
}
|
||||
|
||||
|
||||
typedef Napi::Value (*StaticMethodCallback)(const Napi::CallbackInfo& info);
|
||||
typedef Napi::Value (*StaticGetterCallback)(const Napi::CallbackInfo& info);
|
||||
typedef void (*StaticSetterCallback)(const Napi::CallbackInfo& info);
|
||||
|
||||
|
||||
#define DECLARE_ES5_CLASS(CLASS, NAME) \
|
||||
static Napi::FunctionReference _ctorEs5; \
|
||||
static const char *_nameEs5; \
|
||||
static void CLASS::_finalizeEs5(napi_env e, void *dest, void* hint); \
|
||||
static napi_value CLASS::_createEs5(napi_env e, napi_callback_info i); \
|
||||
inline void super( \
|
||||
const Napi::CallbackInfo& info, \
|
||||
int argc = 0, \
|
||||
const Napi::Value *argv = nullptr \
|
||||
) { \
|
||||
Napi::Function ctor = _ctorEs5.Value(); \
|
||||
if (ctor.Has("super_")) { \
|
||||
Napi::Function _super = ctor.Get("super_").As<Napi::Function>(); \
|
||||
std::vector<napi_value> args; \
|
||||
for (int i = 0; i < argc; i++) { \
|
||||
args.push_back(argv[i]); \
|
||||
} \
|
||||
_super.Call(info.This(), args); \
|
||||
} \
|
||||
}; \
|
||||
inline static Napi::Function wrap(Napi::Env env) { \
|
||||
napi_value __initResult; \
|
||||
napi_create_function(env, #NAME, 0, CLASS::_createEs5, nullptr, &__initResult); \
|
||||
Napi::Function ctor = Napi::Function(env, __initResult); \
|
||||
_ctorEs5 = Napi::Persistent(ctor); \
|
||||
_ctorEs5.SuppressDestruct(); \
|
||||
return ctor; \
|
||||
}; \
|
||||
inline static Napi::Function wrap( \
|
||||
Napi::Env env, \
|
||||
Napi::Function superCtor \
|
||||
) { \
|
||||
Napi::Function ctor = wrap(env); \
|
||||
inheritEs5(env, ctor, superCtor); \
|
||||
return ctor; \
|
||||
}; \
|
||||
inline static void method( \
|
||||
const char *name, \
|
||||
StaticMethodCallback cb \
|
||||
) { \
|
||||
Napi::Function proto = _ctorEs5.Value().Get("prototype").As<Napi::Function>(); \
|
||||
proto.DefineProperty( \
|
||||
Napi::PropertyDescriptor::Function(proto.Env(), proto, name, cb) \
|
||||
); \
|
||||
}; \
|
||||
inline static void accessorR( \
|
||||
const char *name, \
|
||||
StaticGetterCallback getter \
|
||||
) { \
|
||||
Napi::Function proto = _ctorEs5.Value().Get("prototype").As<Napi::Function>(); \
|
||||
proto.DefineProperty( \
|
||||
Napi::PropertyDescriptor::Accessor(proto.Env(), proto, name, getter) \
|
||||
); \
|
||||
}; \
|
||||
inline static void accessorRw( \
|
||||
const char *name, \
|
||||
StaticGetterCallback getter, \
|
||||
StaticSetterCallback setter \
|
||||
) { \
|
||||
Napi::Function proto = _ctorEs5.Value().Get("prototype").As<Napi::Function>(); \
|
||||
proto.DefineProperty( \
|
||||
Napi::PropertyDescriptor::Accessor( \
|
||||
proto.Env(), \
|
||||
proto, \
|
||||
name, \
|
||||
getter, \
|
||||
setter \
|
||||
) \
|
||||
); \
|
||||
};
|
||||
|
||||
#define JS_GET_THAT(CLASS) \
|
||||
CLASS *that; \
|
||||
Napi::Object thatObj = info.This().As<Napi::Object>(); \
|
||||
napi_unwrap(info.Env(), thatObj.Get(_nameEs5), reinterpret_cast<void**>(&that));
|
||||
|
||||
#define JS_DECLARE_METHOD(CLASS, NAME) \
|
||||
inline static Napi::Value __st_##NAME(const Napi::CallbackInfo &info) { \
|
||||
JS_GET_THAT(CLASS); \
|
||||
return that->__i_##NAME(info); \
|
||||
}; \
|
||||
Napi::Value __i_##NAME(const Napi::CallbackInfo &info);
|
||||
|
||||
#define JS_DECLARE_GETTER(CLASS, NAME) JS_DECLARE_METHOD(CLASS, NAME##Getter)
|
||||
|
||||
#define JS_DECLARE_SETTER(CLASS, NAME) \
|
||||
inline static void __st_##NAME##Setter( \
|
||||
const Napi::CallbackInfo &info \
|
||||
) { \
|
||||
JS_GET_THAT(CLASS); \
|
||||
that->__i_##NAME(info, info[0]); \
|
||||
}; \
|
||||
void __i_##NAME##Setter(const Napi::CallbackInfo &info, const Napi::Value &value);
|
||||
|
||||
#define JS_IMPLEMENT_METHOD(CLASS, NAME) \
|
||||
Napi::Value CLASS::__i_##NAME(const Napi::CallbackInfo &info)
|
||||
|
||||
#define JS_IMPLEMENT_GETTER(CLASS, NAME) JS_IMPLEMENT_METHOD(CLASS, NAME##Getter)
|
||||
|
||||
#define JS_IMPLEMENT_SETTER(CLASS, NAME) \
|
||||
void CLASS::__i_##NAME##Setter( \
|
||||
const Napi::CallbackInfo &info, \
|
||||
const Napi::Value &value \
|
||||
)
|
||||
|
||||
#define JS_ASSIGN_METHOD(NAME) method(#NAME, __st_##NAME)
|
||||
#define JS_ASSIGN_GETTER(NAME) accessorR(#NAME, __st_##NAME##Getter)
|
||||
#define JS_ASSIGN_SETTER(NAME) accessorRw(#NAME, __st_##NAME##Getter, __st_##NAME##Setter)
|
||||
|
||||
#define IMPLEMENT_ES5_CLASS(CLASS) \
|
||||
Napi::FunctionReference CLASS::_ctorEs5; \
|
||||
const char *CLASS::_nameEs5 = "CLASS##__TIMESTAMP__"; \
|
||||
void CLASS::_finalizeEs5(napi_env e, void *dest, void* hint) { \
|
||||
CLASS *instance = reinterpret_cast<CLASS*>(dest); \
|
||||
delete instance; \
|
||||
} \
|
||||
napi_value CLASS::_createEs5(napi_env env, napi_callback_info i) { \
|
||||
Napi::CallbackInfo info(env, i); \
|
||||
CLASS *instance = new CLASS(info); \
|
||||
Napi::Object wrapObj = Napi::Object::New(env); \
|
||||
info.This().As<Napi::Object>().Set(_nameEs5, wrapObj); \
|
||||
napi_wrap(env, wrapObj, instance, CLASS::_finalizeEs5, nullptr, nullptr); \
|
||||
return info.Env().Undefined(); \
|
||||
}
|
||||
|
||||
|
||||
#endif // _ADDON_TOOLS_HPP_
|
||||
|
|
Loading…
Reference in New Issue