• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <cstdio>
3 #include <string>
4 #include "env-inl.h"
5 #include "gtest/gtest.h"
6 #include "js_native_api_v8.h"
7 #include "node_api_internals.h"
8 #include "node_binding.h"
9 #include "node_test_fixture.h"
10 
11 namespace v8impl {
12 
13 using v8::Local;
14 using v8::Object;
15 
16 static napi_env addon_env;
17 static uint32_t finalizer_call_count = 0;
18 
19 class JsNativeApiV8Test : public EnvironmentTestFixture {
20  private:
SetUp()21   void SetUp() override {
22     EnvironmentTestFixture::SetUp();
23     finalizer_call_count = 0;
24   }
25 
TearDown()26   void TearDown() override { NodeTestFixture::TearDown(); }
27 };
28 
TEST_F(JsNativeApiV8Test,Reference)29 TEST_F(JsNativeApiV8Test, Reference) {
30   const v8::HandleScope handle_scope(isolate_);
31   Argv argv;
32 
33   napi_ref ref;
34   void* embedder_fields[v8::kEmbedderFieldsInWeakCallback] = {nullptr, nullptr};
35   v8::WeakCallbackInfo<Reference::SecondPassCallParameterRef>::Callback
36       callback;
37   Reference::SecondPassCallParameterRef* parameter = nullptr;
38 
39   {
40     Env test_env{handle_scope, argv};
41 
42     node::Environment* env = *test_env;
43     node::LoadEnvironment(env, "");
44 
45     napi_addon_register_func init = [](napi_env env, napi_value exports) {
46       addon_env = env;
47       return exports;
48     };
49     Local<Object> module_obj = Object::New(isolate_);
50     Local<Object> exports_obj = Object::New(isolate_);
51     napi_module_register_by_symbol(
52         exports_obj, module_obj, env->context(), init);
53     ASSERT_NE(addon_env, nullptr);
54     node_napi_env internal_env = reinterpret_cast<node_napi_env>(addon_env);
55     EXPECT_EQ(internal_env->node_env(), env);
56 
57     // Create a new scope to manage the handles.
58     {
59       const v8::HandleScope handle_scope(isolate_);
60       napi_value value;
61       napi_create_object(addon_env, &value);
62       // Create a weak reference;
63       napi_add_finalizer(
64           addon_env,
65           value,
66           nullptr,
67           [](napi_env env, void* finalize_data, void* finalize_hint) {
68             finalizer_call_count++;
69           },
70           nullptr,
71           &ref);
72       parameter = reinterpret_cast<Reference*>(ref)->_secondPassParameter;
73     }
74 
75     // We can hardly trigger a non-forced Garbage Collection in a stable way.
76     // Here we just invoke the weak callbacks directly.
77     // The persistant handles should be reset in the weak callback in respect
78     // to the API contract of v8 weak callbacks.
79     v8::WeakCallbackInfo<Reference::SecondPassCallParameterRef> data(
80         reinterpret_cast<v8::Isolate*>(isolate_),
81         parameter,
82         embedder_fields,
83         &callback);
84     Reference::FinalizeCallback(data);
85     EXPECT_EQ(callback, &Reference::SecondPassCallback);
86   }
87   // Env goes out of scope, the environment has been teardown. All node-api ref
88   // trackers should have been destroyed.
89 
90   // Now we call the second pass callback to verify the method do not abort with
91   // memory violations.
92   v8::WeakCallbackInfo<Reference::SecondPassCallParameterRef> data(
93       reinterpret_cast<v8::Isolate*>(isolate_),
94       parameter,
95       embedder_fields,
96       nullptr);
97   Reference::SecondPassCallback(data);
98 
99   // After Environment Teardown
100   EXPECT_EQ(finalizer_call_count, uint32_t(1));
101 }
102 }  // namespace v8impl
103