Add ES5 classes
This commit is contained in:
parent
bb46894d97
commit
98aaf2d4ba
|
@ -1,7 +1,7 @@
|
||||||
#ifndef _ADDON_TOOLS_HPP_
|
#ifndef _ADDON_TOOLS_HPP_
|
||||||
#define _ADDON_TOOLS_HPP_
|
#define _ADDON_TOOLS_HPP_
|
||||||
|
|
||||||
|
#define NODE_ADDON_API_DISABLE_DEPRECATED
|
||||||
#include <napi.h>
|
#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_
|
#endif // _ADDON_TOOLS_HPP_
|
||||||
|
|
Loading…
Reference in New Issue