1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
#include <napi.h>
// The formulaic comment below should accompany any code that results in an
// internal piece of heap data getting created, because each such piece of heap
// data must be attached to an object by way of a deleter which gets called when
// the object gets garbage-collected.
//
// At the very least, you can add a fprintf(stderr, ...) to the deleter in
// napi-inl.h and then count the number of times the deleter prints by running
// node --expose-gc test/thunking_manual.js and counting the number of prints
// between the two rows of dashes. That number should coincide with the number
// of formulaic comments below.
//
// Note that currently this result can only be achieved with node-chakracore,
// because V8 does not garbage-collect classes.
static Napi::Value TestMethod(const Napi::CallbackInfo& /*info*/) {
return Napi::Value();
}
static Napi::Value TestGetter(const Napi::CallbackInfo& /*info*/) {
return Napi::Value();
}
static void TestSetter(const Napi::CallbackInfo& /*info*/) {}
class TestClass : public Napi::ObjectWrap<TestClass> {
public:
TestClass(const Napi::CallbackInfo& info) : ObjectWrap<TestClass>(info) {}
static Napi::Value TestClassStaticMethod(const Napi::CallbackInfo& info) {
return Napi::Number::New(info.Env(), 42);
}
static void TestClassStaticVoidMethod(const Napi::CallbackInfo& /*info*/) {}
Napi::Value TestClassInstanceMethod(const Napi::CallbackInfo& info) {
return Napi::Number::New(info.Env(), 42);
}
void TestClassInstanceVoidMethod(const Napi::CallbackInfo& /*info*/) {}
Napi::Value TestClassInstanceGetter(const Napi::CallbackInfo& info) {
return Napi::Number::New(info.Env(), 42);
}
void TestClassInstanceSetter(const Napi::CallbackInfo& /*info*/,
const Napi::Value& /*new_value*/) {}
static Napi::Function NewClass(Napi::Env env) {
return DefineClass(
env,
"TestClass",
{// Make sure to check that the deleter gets called.
StaticMethod("staticMethod", TestClassStaticMethod),
// Make sure to check that the deleter gets called.
StaticMethod("staticVoidMethod", TestClassStaticVoidMethod),
// Make sure to check that the deleter gets called.
StaticMethod(Napi::Symbol::New(env, "staticMethod"),
TestClassStaticMethod),
// Make sure to check that the deleter gets called.
StaticMethod(Napi::Symbol::New(env, "staticVoidMethod"),
TestClassStaticVoidMethod),
// Make sure to check that the deleter gets called.
InstanceMethod("instanceMethod", &TestClass::TestClassInstanceMethod),
// Make sure to check that the deleter gets called.
InstanceMethod("instanceVoidMethod",
&TestClass::TestClassInstanceVoidMethod),
// Make sure to check that the deleter gets called.
InstanceMethod(Napi::Symbol::New(env, "instanceMethod"),
&TestClass::TestClassInstanceMethod),
// Make sure to check that the deleter gets called.
InstanceMethod(Napi::Symbol::New(env, "instanceVoidMethod"),
&TestClass::TestClassInstanceVoidMethod),
// Make sure to check that the deleter gets called.
InstanceAccessor("instanceAccessor",
&TestClass::TestClassInstanceGetter,
&TestClass::TestClassInstanceSetter)});
}
};
static Napi::Value CreateTestObject(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::Object item = Napi::Object::New(env);
// Make sure to check that the deleter gets called.
item["testMethod"] = Napi::Function::New(env, TestMethod, "testMethod");
item.DefineProperties({
// Make sure to check that the deleter gets called.
Napi::PropertyDescriptor::Accessor(env, item, "accessor_1", TestGetter),
// Make sure to check that the deleter gets called.
Napi::PropertyDescriptor::Accessor(
env, item, std::string("accessor_1_std_string"), TestGetter),
// Make sure to check that the deleter gets called.
Napi::PropertyDescriptor::Accessor(
env,
item,
Napi::String::New(info.Env(), "accessor_1_js_string"),
TestGetter),
// Make sure to check that the deleter gets called.
Napi::PropertyDescriptor::Accessor(
env, item, "accessor_2", TestGetter, TestSetter),
// Make sure to check that the deleter gets called.
Napi::PropertyDescriptor::Accessor(env,
item,
std::string("accessor_2_std_string"),
TestGetter,
TestSetter),
// Make sure to check that the deleter gets called.
Napi::PropertyDescriptor::Accessor(
env,
item,
Napi::String::New(env, "accessor_2_js_string"),
TestGetter,
TestSetter),
Napi::PropertyDescriptor::Value("TestClass", TestClass::NewClass(env)),
});
return item;
}
Napi::Object InitThunkingManual(Napi::Env env) {
Napi::Object exports = Napi::Object::New(env);
exports["createTestObject"] =
Napi::Function::New(env, CreateTestObject, "createTestObject");
return exports;
}
|