File: thunking_manual.cc

package info (click to toggle)
node-addon-api 8.3.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,248 kB
  • sloc: cpp: 15,431; javascript: 5,631; ansic: 157; makefile: 7
file content (127 lines) | stat: -rw-r--r-- 5,366 bytes parent folder | download
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;
}