| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 01eb308 commit 481770a
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2769,10 +2769,12 @@ napi_status NAPI_CDECL napi_create_reference(napi_env env, | |||
| 2769 | 2769 | ||
| 2770 | 2770 | // Deletes a reference. The referenced value is released, and may be GC'd unless | |
| 2771 | 2771 | // there are other references to it. | |
| 2772 | + // For a napi_reference returned from `napi_wrap`, this must be called in the | ||
| 2773 | + // finalizer. | ||
| 2772 | 2774 | napi_status NAPI_CDECL napi_delete_reference(napi_env env, napi_ref ref) { | |
| 2773 | 2775 | // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw | |
| 2774 | 2776 | // JS exceptions. | |
| 2775 | - CHECK_ENV_NOT_IN_GC(env); | ||
| 2777 | + CHECK_ENV(env); | ||
| 2776 | 2778 | CHECK_ARG(env, ref); | |
| 2777 | 2779 | ||
| 2778 | 2780 | delete reinterpret_cast<v8impl::Reference*>(ref); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,17 +3,25 @@ | |||
| 3 | 3 | #include "assert.h" | |
| 4 | 4 | #include "myobject.h" | |
| 5 | 5 | ||
| 6 | + typedef int32_t FinalizerData; | ||
| 7 | + | ||
| 6 | 8 | napi_ref MyObject::constructor; | |
| 7 | 9 | ||
| 8 | 10 | MyObject::MyObject(double value) | |
| 9 | 11 | : value_(value), env_(nullptr), wrapper_(nullptr) {} | |
| 10 | 12 | ||
| 11 | 13 | MyObject::~MyObject() { napi_delete_reference(env_, wrapper_); } | |
| 12 | 14 | ||
| 13 | - void MyObject::Destructor( | ||
| 14 | - napi_env env, void* nativeObject, void* /*finalize_hint*/) { | ||
| 15 | + void MyObject::Destructor(node_api_basic_env env, | ||
| 16 | + void* nativeObject, | ||
| 17 | + void* /*finalize_hint*/) { | ||
| 15 | 18 | MyObject* obj = static_cast<MyObject*>(nativeObject); | |
| 16 | 19 | delete obj; | |
| 20 | + | ||
| 21 | + FinalizerData* data; | ||
| 22 | + NODE_API_BASIC_CALL_RETURN_VOID( | ||
| 23 | + env, napi_get_instance_data(env, reinterpret_cast<void**>(&data))); | ||
| 24 | + *data += 1; | ||
| 17 | 25 | } | |
| 18 | 26 | ||
| 19 | 27 | void MyObject::Init(napi_env env, napi_value exports) { | |
@@ -154,7 +162,7 @@ napi_value MyObject::Multiply(napi_env env, napi_callback_info info) { | |||
| 154 | 162 | } | |
| 155 | 163 | ||
| 156 | 164 | // This finalizer should never be invoked. | |
| 157 | - void ObjectWrapDanglingReferenceFinalizer(napi_env env, | ||
| 165 | + void ObjectWrapDanglingReferenceFinalizer(node_api_basic_env env, | ||
| 158 | 166 | void* finalize_data, | |
| 159 | 167 | void* finalize_hint) { | |
| 160 | 168 | assert(0 && "unreachable"); | |
@@ -198,15 +206,38 @@ napi_value ObjectWrapDanglingReferenceTest(napi_env env, | |||
| 198 | 206 | return ret; | |
| 199 | 207 | } | |
| 200 | 208 | ||
| 209 | + static napi_value GetFinalizerCallCount(napi_env env, napi_callback_info info) { | ||
| 210 | + size_t argc = 1; | ||
| 211 | + napi_value argv[1]; | ||
| 212 | + FinalizerData* data; | ||
| 213 | + napi_value result; | ||
| 214 | + | ||
| 215 | + NODE_API_CALL(env, | ||
| 216 | + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr)); | ||
| 217 | + NODE_API_CALL(env, | ||
| 218 | + napi_get_instance_data(env, reinterpret_cast<void**>(&data))); | ||
| 219 | + NODE_API_CALL(env, napi_create_int32(env, *data, &result)); | ||
| 220 | + return result; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + static void finalizeData(napi_env env, void* data, void* hint) { | ||
| 224 | + delete reinterpret_cast<FinalizerData*>(data); | ||
| 225 | + } | ||
| 226 | + | ||
| 201 | 227 | EXTERN_C_START | |
| 202 | 228 | napi_value Init(napi_env env, napi_value exports) { | |
| 229 | + FinalizerData* data = new FinalizerData; | ||
| 230 | + *data = 0; | ||
| 231 | + NODE_API_CALL(env, napi_set_instance_data(env, data, finalizeData, nullptr)); | ||
| 232 | + | ||
| 203 | 233 | MyObject::Init(env, exports); | |
| 204 | 234 | ||
| 205 | 235 | napi_property_descriptor descriptors[] = { | |
| 206 | 236 | DECLARE_NODE_API_PROPERTY("objectWrapDanglingReference", | |
| 207 | 237 | ObjectWrapDanglingReference), | |
| 208 | 238 | DECLARE_NODE_API_PROPERTY("objectWrapDanglingReferenceTest", | |
| 209 | 239 | ObjectWrapDanglingReferenceTest), | |
| 240 | + DECLARE_NODE_API_PROPERTY("getFinalizerCallCount", GetFinalizerCallCount), | ||
| 210 | 241 | }; | |
| 211 | 242 | ||
| 212 | 243 | NODE_API_CALL( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,13 @@ | |||
| 5 | 5 | "sources": [ | |
| 6 | 6 | "6_object_wrap.cc" | |
| 7 | 7 | ] | |
| 8 | + }, | ||
| 9 | + { | ||
| 10 | + "target_name": "6_object_wrap_basic_finalizer", | ||
| 11 | + "defines": [ "NAPI_EXPERIMENTAL" ], | ||
| 12 | + "sources": [ | ||
| 13 | + "6_object_wrap.cc" | ||
| 14 | + ] | ||
| 8 | 15 | } | |
| 9 | 16 | ] | |
| 10 | 17 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,7 +6,9 @@ | |||
| 6 | 6 | class MyObject { | |
| 7 | 7 | public: | |
| 8 | 8 | static void Init(napi_env env, napi_value exports); | |
| 9 | - static void Destructor(napi_env env, void* nativeObject, void* finalize_hint); | ||
| 9 | + static void Destructor(node_api_basic_env env, | ||
| 10 | + void* nativeObject, | ||
| 11 | + void* finalize_hint); | ||
| 10 | 12 | ||
| 11 | 13 | private: | |
| 12 | 14 | explicit MyObject(double value_ = 0); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,24 @@ | |||
| 1 | + // Flags: --expose-gc | ||
| 2 | + | ||
| 3 | + 'use strict'; | ||
| 4 | + const common = require('../../common'); | ||
| 5 | + const assert = require('assert'); | ||
| 6 | + const addon = require(`./build/${common.buildType}/6_object_wrap_basic_finalizer`); | ||
| 7 | + | ||
| 8 | + // This test verifies that ObjectWrap can be correctly finalized with a node_api_basic_finalizer | ||
| 9 | + // in the current JS loop tick | ||
| 10 | + (() => { | ||
| 11 | + let obj = new addon.MyObject(9); | ||
| 12 | + obj = null; | ||
| 13 | + // Silent eslint about unused variables. | ||
| 14 | + assert.strictEqual(obj, null); | ||
| 15 | + })(); | ||
| 16 | + | ||
| 17 | + for (let i = 0; i < 10; ++i) { | ||
| 18 | + global.gc(); | ||
| 19 | + if (addon.getFinalizerCallCount() === 1) { | ||
| 20 | + break; | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + assert.strictEqual(addon.getFinalizerCallCount(), 1); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments