|
1 | 1 | #include "myobject.h" |
2 | 2 | #include <assert.h> |
3 | 3 |
|
4 | | -napi_ref MyObject::constructor; |
5 | | - |
6 | 4 | MyObject::MyObject(double value) |
7 | 5 | : value_(value), env_(nullptr), wrapper_(nullptr) {} |
8 | 6 |
|
@@ -32,14 +30,46 @@ napi_value MyObject::Init(napi_env env, napi_value exports) { |
32 | 30 | env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 3, properties, &cons); |
33 | 31 | assert(status == napi_ok); |
34 | 32 |
|
35 | | - status = napi_create_reference(env, cons, 1, &constructor); |
| 33 | + // We will need the constructor `cons` later during the life cycle of the |
| 34 | + // addon, so we store a persistent reference to it as the instance data for |
| 35 | + // our addon. This will enable us to use `napi_get_instance_data` at any |
| 36 | + // point during the life cycle of our addon to retrieve it. We cannot simply |
| 37 | + // store it as a global static variable, because that will render our addon |
| 38 | + // unable to support Node.js worker threads and multiple contexts on a single |
| 39 | + // thread. |
| 40 | + // |
| 41 | + // The finalizer we pass as a lambda will be called when our addon is unloaded |
| 42 | + // and is responsible for releasing the persistent reference and freeing the |
| 43 | + // heap memory where we stored the persistent reference. |
| 44 | + napi_ref* constructor = new napi_ref; |
| 45 | + status = napi_create_reference(env, cons, 1, constructor); |
| 46 | + assert(status == napi_ok); |
| 47 | + status = napi_set_instance_data(env, constructor, |
| 48 | + [](napi_env env, void* data, void* hint) { |
| 49 | + napi_ref* constructor = static_cast<napi_ref*>(data); |
| 50 | + napi_status status = napi_delete_reference(env, *constructor); |
| 51 | + assert(status == napi_ok); |
| 52 | + delete constructor; |
| 53 | + }, nullptr); |
36 | 54 | assert(status == napi_ok); |
37 | 55 |
|
38 | 56 | status = napi_set_named_property(env, exports, "MyObject", cons); |
39 | 57 | assert(status == napi_ok); |
40 | 58 | return exports; |
41 | 59 | } |
42 | 60 |
|
| 61 | +napi_value MyObject::Constructor(napi_env env) { |
| 62 | + void* instance_data = nullptr; |
| 63 | + napi_status status = napi_get_instance_data(env, &instance_data); |
| 64 | + assert(status == napi_ok); |
| 65 | + napi_ref* constructor = static_cast<napi_ref*>(instance_data); |
| 66 | + |
| 67 | + napi_value cons; |
| 68 | + status = napi_get_reference_value(env, *constructor, &cons); |
| 69 | + assert(status == napi_ok); |
| 70 | + return cons; |
| 71 | +} |
| 72 | + |
43 | 73 | napi_value MyObject::New(napi_env env, napi_callback_info info) { |
44 | 74 | napi_status status; |
45 | 75 |
|
@@ -89,12 +119,8 @@ napi_value MyObject::New(napi_env env, napi_callback_info info) { |
89 | 119 | const size_t argc = 1; |
90 | 120 | napi_value argv[argc] = {args[0]}; |
91 | 121 |
|
92 | | - napi_value cons; |
93 | | - status = napi_get_reference_value(env, constructor, &cons); |
94 | | - assert(status == napi_ok); |
95 | | - |
96 | 122 | napi_value instance; |
97 | | - status = napi_new_instance(env, cons, argc, argv, &instance); |
| 123 | + status = napi_new_instance(env, Constructor(env), argc, argv, &instance); |
98 | 124 | assert(status == napi_ok); |
99 | 125 |
|
100 | 126 | return instance; |
@@ -181,17 +207,13 @@ napi_value MyObject::Multiply(napi_env env, napi_callback_info info) { |
181 | 207 | status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); |
182 | 208 | assert(status == napi_ok); |
183 | 209 |
|
184 | | - napi_value cons; |
185 | | - status = napi_get_reference_value(env, constructor, &cons); |
186 | | - assert(status == napi_ok); |
187 | | - |
188 | 210 | const int kArgCount = 1; |
189 | 211 | napi_value argv[kArgCount]; |
190 | 212 | status = napi_create_double(env, obj->value_ * multiple, argv); |
191 | 213 | assert(status == napi_ok); |
192 | 214 |
|
193 | 215 | napi_value instance; |
194 | | - status = napi_new_instance(env, cons, kArgCount, argv, &instance); |
| 216 | + status = napi_new_instance(env, Constructor(env), kArgCount, argv, &instance); |
195 | 217 | assert(status == napi_ok); |
196 | 218 |
|
197 | 219 | return instance; |
|
0 commit comments