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