Skip to content

Instantly share code, notes, and snippets.

@ApsarasX
Last active April 24, 2021 10:13
Show Gist options
  • Save ApsarasX/41424e9bdccaf2490b34e85e7a6a5f8a to your computer and use it in GitHub Desktop.
Save ApsarasX/41424e9bdccaf2490b34e85e7a6a5f8a to your computer and use it in GitHub Desktop.
// Type and StructType both inherit Napi::ObjectWrap.
// And they both have a static member called constructor `static inline Napi::FunctionReference constructor;`
void StructType::Init(Napi::Env env, Napi::Object &exports) {
Napi::HandleScope scope(env);
Napi::Function super_func = Type::constructor.Value();
napi_value super_ctor = napi_value(super_func);
Napi::Function func = DefineSubClass(env, super_ctor, "StructType", {
StaticMethod("create", &StructType::create),
InstanceMethod("setBody", &StructType::setBody)
});
constructor = Napi::Persistent(func);
constructor.SuppressDestruct();
exports.Set("StructType", func);
}
// README: this code is a part in my repo llvm-bindings, in 'https://github.com/ApsarasX/llvm-bindings/blob/master/src/IR/StructType.cpp'
static napi_value ProcessSuperParams(napi_env env, napi_callback_info info) {
napi_value ar;
NAPI_THROW_IF_FAILED_VOID(env, napi_create_array(env, &ar));
return ar;
}
template <typename T>
inline Function
ObjectWrap<T>::DefineSubClass(
Napi::Env env,
napi_value super_ctor,
const char* utf8name,
const size_t props_count,
const napi_property_descriptor* descriptors,
void* data) {
napi_status status;
std::vector<napi_property_descriptor> props(props_count);
for (size_t index = 0; index < props_count; index++) {
props[index] = descriptors[index];
napi_property_descriptor* prop = &props[index];
if (prop->method == T::StaticMethodCallbackWrapper) {
status = CreateFunction(env,
utf8name,
prop->method,
static_cast<StaticMethodCallbackData*>(prop->data),
&(prop->value));
NAPI_THROW_IF_FAILED(env, status, Function());
prop->method = nullptr;
prop->data = nullptr;
} else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
status = CreateFunction(env,
utf8name,
prop->method,
static_cast<StaticVoidMethodCallbackData*>(prop->data),
&(prop->value));
NAPI_THROW_IF_FAILED(env, status, Function());
prop->method = nullptr;
prop->data = nullptr;
}
}
napi_value value;
// status = napi_define_class(env,
// utf8name,
// NAPI_AUTO_LENGTH,
// T::ConstructorCallbackWrapper,
// data,
// props_count,
// props.data(),
// &value);
status = napi_define_subclass(
env,
super_ctor,
utf8name,
NAPI_AUTO_LENGTH,
T::ConstructorCallbackWrapper,
ProcessSuperParams,
data,
props_count,
props.data(),
&value
);
NAPI_THROW_IF_FAILED(env, status, Function());
// After defining the class we iterate once more over the property descriptors
// and attach the data associated with accessors and instance methods to the
// newly created JavaScript class.
for (size_t idx = 0; idx < props_count; idx++) {
const napi_property_descriptor* prop = &props[idx];
if (prop->getter == T::StaticGetterCallbackWrapper ||
prop->setter == T::StaticSetterCallbackWrapper) {
status = Napi::details::AttachData(env,
value,
static_cast<StaticAccessorCallbackData*>(prop->data));
NAPI_THROW_IF_FAILED(env, status, Function());
} else {
// InstanceWrap<T>::AttachPropData is responsible for attaching the data
// of instance methods and accessors.
T::AttachPropData(env, value, prop);
}
}
return Function(env, value);
}
template <typename T>
inline Function ObjectWrap<T>::DefineSubClass(
Napi::Env env,
napi_value super_ctor,
const char* utf8name,
const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
void* data) {
return DefineSubClass(env,
super_ctor,
utf8name,
properties.size(),
reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
data);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment