• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #ifndef SRC_BASE_OBJECT_INL_H_
23 #define SRC_BASE_OBJECT_INL_H_
24 
25 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26 
27 #include "base_object.h"
28 #include "env-inl.h"
29 #include "util.h"
30 
31 #include "v8.h"
32 
33 namespace node {
34 
BaseObject(Environment * env,v8::Local<v8::Object> object)35 BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> object)
36     : BaseObject(env->principal_realm(), object) {
37   // TODO(legendecas): Check the shorthand is only used in the principal realm
38   // while allowing to create a BaseObject in a vm context.
39 }
40 
41 // static
GetConstructorTemplate(Environment * env)42 v8::Local<v8::FunctionTemplate> BaseObject::GetConstructorTemplate(
43     Environment* env) {
44   return BaseObject::GetConstructorTemplate(env->isolate_data());
45 }
46 
Detach()47 void BaseObject::Detach() {
48   CHECK_GT(pointer_data()->strong_ptr_count, 0);
49   pointer_data()->is_detached = true;
50 }
51 
persistent()52 v8::Global<v8::Object>& BaseObject::persistent() {
53   return persistent_handle_;
54 }
55 
56 
object()57 v8::Local<v8::Object> BaseObject::object() const {
58   return PersistentToLocal::Default(env()->isolate(), persistent_handle_);
59 }
60 
object(v8::Isolate * isolate)61 v8::Local<v8::Object> BaseObject::object(v8::Isolate* isolate) const {
62   v8::Local<v8::Object> handle = object();
63 
64   DCHECK_EQ(handle->GetCreationContext().ToLocalChecked()->GetIsolate(),
65             isolate);
66   DCHECK_EQ(env()->isolate(), isolate);
67 
68   return handle;
69 }
70 
env()71 Environment* BaseObject::env() const {
72   return realm_->env();
73 }
74 
realm()75 Realm* BaseObject::realm() const {
76   return realm_;
77 }
78 
TagNodeObject(v8::Local<v8::Object> object)79 void BaseObject::TagNodeObject(v8::Local<v8::Object> object) {
80   DCHECK_GE(object->InternalFieldCount(), BaseObject::kInternalFieldCount);
81   object->SetAlignedPointerInInternalField(BaseObject::kEmbedderType,
82                                            &kNodeEmbedderId);
83 }
84 
SetInternalFields(v8::Local<v8::Object> object,void * slot)85 void BaseObject::SetInternalFields(v8::Local<v8::Object> object, void* slot) {
86   TagNodeObject(object);
87   object->SetAlignedPointerInInternalField(BaseObject::kSlot, slot);
88 }
89 
FromJSObject(v8::Local<v8::Value> value)90 BaseObject* BaseObject::FromJSObject(v8::Local<v8::Value> value) {
91   v8::Local<v8::Object> obj = value.As<v8::Object>();
92   DCHECK_GE(obj->InternalFieldCount(), BaseObject::kInternalFieldCount);
93   return static_cast<BaseObject*>(
94       obj->GetAlignedPointerFromInternalField(BaseObject::kSlot));
95 }
96 
97 template <typename T>
FromJSObject(v8::Local<v8::Value> object)98 T* BaseObject::FromJSObject(v8::Local<v8::Value> object) {
99   return static_cast<T*>(FromJSObject(object));
100 }
101 
OnGCCollect()102 void BaseObject::OnGCCollect() {
103   delete this;
104 }
105 
ClearWeak()106 void BaseObject::ClearWeak() {
107   if (has_pointer_data())
108     pointer_data()->wants_weak_jsobj = false;
109 
110   persistent_handle_.ClearWeak();
111 }
112 
IsWeakOrDetached()113 bool BaseObject::IsWeakOrDetached() const {
114   if (persistent_handle_.IsWeak()) return true;
115 
116   if (!has_pointer_data()) return false;
117   const PointerData* pd = const_cast<BaseObject*>(this)->pointer_data();
118   return pd->wants_weak_jsobj || pd->is_detached;
119 }
120 
GetDetachedness()121 v8::EmbedderGraph::Node::Detachedness BaseObject::GetDetachedness() const {
122   return IsWeakOrDetached() ? v8::EmbedderGraph::Node::Detachedness::kDetached
123                             : v8::EmbedderGraph::Node::Detachedness::kUnknown;
124 }
125 
126 template <int Field>
InternalFieldGet(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)127 void BaseObject::InternalFieldGet(
128     v8::Local<v8::String> property,
129     const v8::PropertyCallbackInfo<v8::Value>& info) {
130   info.GetReturnValue().Set(info.This()->GetInternalField(Field));
131 }
132 
133 template <int Field, bool (v8::Value::* typecheck)() const>
InternalFieldSet(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)134 void BaseObject::InternalFieldSet(v8::Local<v8::String> property,
135                                   v8::Local<v8::Value> value,
136                                   const v8::PropertyCallbackInfo<void>& info) {
137   // This could be e.g. value->IsFunction().
138   CHECK(((*value)->*typecheck)());
139   info.This()->SetInternalField(Field, value);
140 }
141 
has_pointer_data()142 bool BaseObject::has_pointer_data() const {
143   return pointer_data_ != nullptr;
144 }
145 
146 template <typename T, bool kIsWeak>
147 BaseObject::PointerData*
pointer_data()148 BaseObjectPtrImpl<T, kIsWeak>::pointer_data() const {
149   if constexpr (kIsWeak) {
150     return data_.pointer_data;
151   }
152   if (get_base_object() == nullptr) {
153     return nullptr;
154   }
155   return get_base_object()->pointer_data();
156 }
157 
158 template <typename T, bool kIsWeak>
get_base_object()159 BaseObject* BaseObjectPtrImpl<T, kIsWeak>::get_base_object() const {
160   if constexpr (kIsWeak) {
161     if (pointer_data() == nullptr) {
162       return nullptr;
163     }
164     return pointer_data()->self;
165   }
166   return data_.target;
167 }
168 
169 template <typename T, bool kIsWeak>
~BaseObjectPtrImpl()170 BaseObjectPtrImpl<T, kIsWeak>::~BaseObjectPtrImpl() {
171   if constexpr (kIsWeak) {
172     if (pointer_data() != nullptr &&
173         --pointer_data()->weak_ptr_count == 0 &&
174         pointer_data()->self == nullptr) {
175       delete pointer_data();
176     }
177   } else if (get() != nullptr) {
178     get()->decrease_refcount();
179   }
180 }
181 
182 template <typename T, bool kIsWeak>
BaseObjectPtrImpl()183 BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl() {
184   data_.target = nullptr;
185 }
186 
187 template <typename T, bool kIsWeak>
BaseObjectPtrImpl(T * target)188 BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(T* target)
189   : BaseObjectPtrImpl() {
190   if (target == nullptr) return;
191   if constexpr (kIsWeak) {
192     data_.pointer_data = target->pointer_data();
193     CHECK_NOT_NULL(pointer_data());
194     pointer_data()->weak_ptr_count++;
195   } else {
196     data_.target = target;
197     CHECK_NOT_NULL(pointer_data());
198     get()->increase_refcount();
199   }
200 }
201 
202 template <typename T, bool kIsWeak>
203 template <typename U, bool kW>
BaseObjectPtrImpl(const BaseObjectPtrImpl<U,kW> & other)204 BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(
205     const BaseObjectPtrImpl<U, kW>& other)
206   : BaseObjectPtrImpl(other.get()) {}
207 
208 template <typename T, bool kIsWeak>
BaseObjectPtrImpl(const BaseObjectPtrImpl & other)209 BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(const BaseObjectPtrImpl& other)
210   : BaseObjectPtrImpl(other.get()) {}
211 
212 template <typename T, bool kIsWeak>
213 template <typename U, bool kW>
214 BaseObjectPtrImpl<T, kIsWeak>& BaseObjectPtrImpl<T, kIsWeak>::operator=(
215     const BaseObjectPtrImpl<U, kW>& other) {
216   if (other.get() == get()) return *this;
217   this->~BaseObjectPtrImpl();
218   return *new (this) BaseObjectPtrImpl(other);
219 }
220 
221 template <typename T, bool kIsWeak>
222 BaseObjectPtrImpl<T, kIsWeak>& BaseObjectPtrImpl<T, kIsWeak>::operator=(
223     const BaseObjectPtrImpl& other) {
224   if (other.get() == get()) return *this;
225   this->~BaseObjectPtrImpl();
226   return *new (this) BaseObjectPtrImpl(other);
227 }
228 
229 template <typename T, bool kIsWeak>
BaseObjectPtrImpl(BaseObjectPtrImpl && other)230 BaseObjectPtrImpl<T, kIsWeak>::BaseObjectPtrImpl(BaseObjectPtrImpl&& other)
231   : data_(other.data_) {
232   if constexpr (kIsWeak)
233     other.data_.target = nullptr;
234   else
235     other.data_.pointer_data = nullptr;
236 }
237 
238 template <typename T, bool kIsWeak>
239 BaseObjectPtrImpl<T, kIsWeak>& BaseObjectPtrImpl<T, kIsWeak>::operator=(
240     BaseObjectPtrImpl&& other) {
241   if (&other == this) return *this;
242   this->~BaseObjectPtrImpl();
243   return *new (this) BaseObjectPtrImpl(std::move(other));
244 }
245 
246 template <typename T, bool kIsWeak>
reset(T * ptr)247 void BaseObjectPtrImpl<T, kIsWeak>::reset(T* ptr) {
248   *this = BaseObjectPtrImpl(ptr);
249 }
250 
251 template <typename T, bool kIsWeak>
get()252 T* BaseObjectPtrImpl<T, kIsWeak>::get() const {
253   return static_cast<T*>(get_base_object());
254 }
255 
256 template <typename T, bool kIsWeak>
257 T& BaseObjectPtrImpl<T, kIsWeak>::operator*() const {
258   return *get();
259 }
260 
261 template <typename T, bool kIsWeak>
262 T* BaseObjectPtrImpl<T, kIsWeak>::operator->() const {
263   return get();
264 }
265 
266 template <typename T, bool kIsWeak>
267 BaseObjectPtrImpl<T, kIsWeak>::operator bool() const {
268   return get() != nullptr;
269 }
270 
271 template <typename T, bool kIsWeak>
272 template <typename U, bool kW>
273 bool BaseObjectPtrImpl<T, kIsWeak>::operator ==(
274     const BaseObjectPtrImpl<U, kW>& other) const {
275   return get() == other.get();
276 }
277 
278 template <typename T, bool kIsWeak>
279 template <typename U, bool kW>
280 bool BaseObjectPtrImpl<T, kIsWeak>::operator !=(
281     const BaseObjectPtrImpl<U, kW>& other) const {
282   return get() != other.get();
283 }
284 
285 template <typename T, typename... Args>
MakeBaseObject(Args &&...args)286 BaseObjectPtr<T> MakeBaseObject(Args&&... args) {
287   return BaseObjectPtr<T>(new T(std::forward<Args>(args)...));
288 }
289 
290 template <typename T, typename... Args>
MakeDetachedBaseObject(Args &&...args)291 BaseObjectPtr<T> MakeDetachedBaseObject(Args&&... args) {
292   BaseObjectPtr<T> target = MakeBaseObject<T>(std::forward<Args>(args)...);
293   target->Detach();
294   return target;
295 }
296 
297 }  // namespace node
298 
299 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
300 
301 #endif  // SRC_BASE_OBJECT_INL_H_
302