1 /********************************************************************* 2 * NAN - Native Abstractions for Node.js 3 * 4 * Copyright (c) 2018 NAN contributors 5 * 6 * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md> 7 ********************************************************************/ 8 9 #ifndef NAN_OBJECT_WRAP_H_ 10 #define NAN_OBJECT_WRAP_H_ 11 12 class ObjectWrap { 13 public: ObjectWrap()14 ObjectWrap() { 15 refs_ = 0; 16 } 17 18 ~ObjectWrap()19 virtual ~ObjectWrap() { 20 if (persistent().IsEmpty()) { 21 return; 22 } 23 24 persistent().ClearWeak(); 25 persistent().Reset(); 26 } 27 28 29 template <class T> Unwrap(v8::Local<v8::Object> object)30 static inline T* Unwrap(v8::Local<v8::Object> object) { 31 assert(!object.IsEmpty()); 32 assert(object->InternalFieldCount() > 0); 33 // Cast to ObjectWrap before casting to T. A direct cast from void 34 // to T won't work right when T has more than one base class. 35 void* ptr = GetInternalFieldPointer(object, 0); 36 ObjectWrap* wrap = static_cast<ObjectWrap*>(ptr); 37 return static_cast<T*>(wrap); 38 } 39 40 handle()41 inline v8::Local<v8::Object> handle() const { 42 return New(handle_); 43 } 44 45 persistent()46 inline Persistent<v8::Object>& persistent() { 47 return handle_; 48 } 49 50 51 protected: Wrap(v8::Local<v8::Object> object)52 inline void Wrap(v8::Local<v8::Object> object) { 53 assert(persistent().IsEmpty()); 54 assert(object->InternalFieldCount() > 0); 55 SetInternalFieldPointer(object, 0, this); 56 persistent().Reset(object); 57 MakeWeak(); 58 } 59 60 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ 61 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) 62 MakeWeak()63 inline void MakeWeak() { 64 persistent().v8::PersistentBase<v8::Object>::SetWeak( 65 this, WeakCallback, v8::WeakCallbackType::kParameter); 66 #if NODE_MAJOR_VERSION < 10 67 // FIXME(bnoordhuis) Probably superfluous in older Node.js versions too. 68 persistent().MarkIndependent(); 69 #endif 70 } 71 72 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION 73 MakeWeak()74 inline void MakeWeak() { 75 persistent().v8::PersistentBase<v8::Object>::SetWeak(this, WeakCallback); 76 persistent().MarkIndependent(); 77 } 78 79 #else 80 MakeWeak()81 inline void MakeWeak() { 82 persistent().persistent.MakeWeak(this, WeakCallback); 83 persistent().MarkIndependent(); 84 } 85 86 #endif 87 88 /* Ref() marks the object as being attached to an event loop. 89 * Refed objects will not be garbage collected, even if 90 * all references are lost. 91 */ Ref()92 virtual void Ref() { 93 assert(!persistent().IsEmpty()); 94 persistent().ClearWeak(); 95 refs_++; 96 } 97 98 /* Unref() marks an object as detached from the event loop. This is its 99 * default state. When an object with a "weak" reference changes from 100 * attached to detached state it will be freed. Be careful not to access 101 * the object after making this call as it might be gone! 102 * (A "weak reference" means an object that only has a 103 * persistent handle.) 104 * 105 * DO NOT CALL THIS FROM DESTRUCTOR 106 */ Unref()107 virtual void Unref() { 108 assert(!persistent().IsEmpty()); 109 assert(!persistent().IsWeak()); 110 assert(refs_ > 0); 111 if (--refs_ == 0) 112 MakeWeak(); 113 } 114 115 int refs_; // ro 116 117 private: NAN_DISALLOW_ASSIGN_COPY_MOVE(ObjectWrap)118 NAN_DISALLOW_ASSIGN_COPY_MOVE(ObjectWrap) 119 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ 120 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) 121 122 static void 123 WeakCallback(v8::WeakCallbackInfo<ObjectWrap> const& info) { 124 ObjectWrap* wrap = info.GetParameter(); 125 assert(wrap->refs_ == 0); 126 wrap->handle_.Reset(); 127 delete wrap; 128 } 129 130 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION 131 132 static void 133 WeakCallback(v8::WeakCallbackData<v8::Object, ObjectWrap> const& data) { 134 ObjectWrap* wrap = data.GetParameter(); 135 assert(wrap->refs_ == 0); 136 assert(wrap->handle_.IsNearDeath()); 137 wrap->handle_.Reset(); 138 delete wrap; 139 } 140 141 #else 142 143 static void WeakCallback(v8::Persistent<v8::Value> value, void *data) { 144 ObjectWrap *wrap = static_cast<ObjectWrap*>(data); 145 assert(wrap->refs_ == 0); 146 assert(wrap->handle_.IsNearDeath()); 147 wrap->handle_.Reset(); 148 delete wrap; 149 } 150 151 #endif 152 Persistent<v8::Object> handle_; 153 }; 154 155 156 #endif // NAN_OBJECT_WRAP_H_ 157