• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "base_object-inl.h"
2 #include "gtest/gtest.h"
3 #include "node.h"
4 #include "node_realm-inl.h"
5 #include "node_test_fixture.h"
6 
7 using node::BaseObject;
8 using node::BaseObjectPtr;
9 using node::BaseObjectWeakPtr;
10 using node::Environment;
11 using node::MakeBaseObject;
12 using node::MakeDetachedBaseObject;
13 using node::Realm;
14 using v8::HandleScope;
15 using v8::Isolate;
16 using v8::Local;
17 using v8::Object;
18 
19 class BaseObjectPtrTest : public EnvironmentTestFixture {};
20 
21 class DummyBaseObject : public BaseObject {
22  public:
DummyBaseObject(Environment * env,Local<Object> obj)23   DummyBaseObject(Environment* env, Local<Object> obj) : BaseObject(env, obj) {}
24 
MakeJSObject(Environment * env)25   static Local<Object> MakeJSObject(Environment* env) {
26     return BaseObject::MakeLazilyInitializedJSTemplate(env)
27         ->GetFunction(env->context()).ToLocalChecked()
28         ->NewInstance(env->context()).ToLocalChecked();
29   }
30 
NewDetached(Environment * env)31   static BaseObjectPtr<DummyBaseObject> NewDetached(Environment* env) {
32     Local<Object> obj = MakeJSObject(env);
33     return MakeDetachedBaseObject<DummyBaseObject>(env, obj);
34   }
35 
New(Environment * env)36   static BaseObjectPtr<DummyBaseObject> New(Environment* env) {
37     Local<Object> obj = MakeJSObject(env);
38     return MakeBaseObject<DummyBaseObject>(env, obj);
39   }
40 
41   SET_NO_MEMORY_INFO()
42   SET_MEMORY_INFO_NAME(DummyBaseObject)
43   SET_SELF_SIZE(DummyBaseObject)
44 };
45 
TEST_F(BaseObjectPtrTest,ScopedDetached)46 TEST_F(BaseObjectPtrTest, ScopedDetached) {
47   const HandleScope handle_scope(isolate_);
48   const Argv argv;
49   Env env_{handle_scope, argv};
50   Environment* env = *env_;
51   Realm* realm = env->principal_realm();
52 
53   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
54   {
55     BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
56     EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
57   }
58   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
59 }
60 
TEST_F(BaseObjectPtrTest,ScopedDetachedWithWeak)61 TEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) {
62   const HandleScope handle_scope(isolate_);
63   const Argv argv;
64   Env env_{handle_scope, argv};
65   Environment* env = *env_;
66   Realm* realm = env->principal_realm();
67 
68   BaseObjectWeakPtr<DummyBaseObject> weak_ptr;
69 
70   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
71   {
72     BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
73     weak_ptr = ptr;
74     EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
75   }
76   EXPECT_EQ(weak_ptr.get(), nullptr);
77   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
78 }
79 
TEST_F(BaseObjectPtrTest,Undetached)80 TEST_F(BaseObjectPtrTest, Undetached) {
81   const HandleScope handle_scope(isolate_);
82   const Argv argv;
83   Env env_{handle_scope, argv};
84   Environment* env = *env_;
85   Realm* realm = env->principal_realm();
86 
87   node::AddEnvironmentCleanupHook(
88       isolate_,
89       [](void* arg) {
90         EXPECT_EQ(static_cast<Realm*>(arg)->base_object_count(), 0);
91       },
92       realm);
93 
94   BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::New(env);
95   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
96 }
97 
TEST_F(BaseObjectPtrTest,GCWeak)98 TEST_F(BaseObjectPtrTest, GCWeak) {
99   const HandleScope handle_scope(isolate_);
100   const Argv argv;
101   Env env_{handle_scope, argv};
102   Environment* env = *env_;
103   Realm* realm = env->principal_realm();
104 
105   BaseObjectWeakPtr<DummyBaseObject> weak_ptr;
106 
107   {
108     const HandleScope handle_scope(isolate_);
109     BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::New(env);
110     weak_ptr = ptr;
111     ptr->MakeWeak();
112 
113     EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
114     EXPECT_EQ(weak_ptr.get(), ptr.get());
115     EXPECT_EQ(weak_ptr->persistent().IsWeak(), false);
116 
117     ptr.reset();
118   }
119 
120   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
121   EXPECT_NE(weak_ptr.get(), nullptr);
122   EXPECT_EQ(weak_ptr->persistent().IsWeak(), true);
123 
124   v8::V8::SetFlagsFromString("--expose-gc");
125   isolate_->RequestGarbageCollectionForTesting(Isolate::kFullGarbageCollection);
126 
127   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
128   EXPECT_EQ(weak_ptr.get(), nullptr);
129 }
130 
TEST_F(BaseObjectPtrTest,Moveable)131 TEST_F(BaseObjectPtrTest, Moveable) {
132   const HandleScope handle_scope(isolate_);
133   const Argv argv;
134   Env env_{handle_scope, argv};
135   Environment* env = *env_;
136   Realm* realm = env->principal_realm();
137 
138   BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
139   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
140   BaseObjectWeakPtr<DummyBaseObject> weak_ptr { ptr };
141   EXPECT_EQ(weak_ptr.get(), ptr.get());
142 
143   BaseObjectPtr<DummyBaseObject> ptr2 = std::move(ptr);
144   EXPECT_EQ(weak_ptr.get(), ptr2.get());
145   EXPECT_EQ(ptr.get(), nullptr);
146 
147   BaseObjectWeakPtr<DummyBaseObject> weak_ptr2 = std::move(weak_ptr);
148   EXPECT_EQ(weak_ptr2.get(), ptr2.get());
149   EXPECT_EQ(weak_ptr.get(), nullptr);
150   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
151 
152   ptr2.reset();
153 
154   EXPECT_EQ(weak_ptr2.get(), nullptr);
155   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
156 }
157 
TEST_F(BaseObjectPtrTest,NestedClasses)158 TEST_F(BaseObjectPtrTest, NestedClasses) {
159   class ObjectWithPtr : public BaseObject {
160    public:
161     ObjectWithPtr(Environment* env, Local<Object> obj) : BaseObject(env, obj) {}
162 
163     BaseObjectPtr<BaseObject> ptr1;
164     BaseObjectPtr<BaseObject> ptr2;
165 
166     SET_NO_MEMORY_INFO()
167     SET_MEMORY_INFO_NAME(ObjectWithPtr)
168     SET_SELF_SIZE(ObjectWithPtr)
169   };
170 
171   const HandleScope handle_scope(isolate_);
172   const Argv argv;
173   Env env_{handle_scope, argv};
174   Environment* env = *env_;
175   Realm* realm = env->principal_realm();
176 
177   node::AddEnvironmentCleanupHook(
178       isolate_,
179       [](void* arg) {
180         EXPECT_EQ(static_cast<Realm*>(arg)->base_object_count(), 0);
181       },
182       realm);
183 
184   ObjectWithPtr* obj =
185       new ObjectWithPtr(env, DummyBaseObject::MakeJSObject(env));
186   obj->ptr1 = DummyBaseObject::NewDetached(env);
187   obj->ptr2 = DummyBaseObject::New(env);
188 
189   EXPECT_EQ(realm->base_object_created_after_bootstrap(), 3);
190 }
191