00001 /********************************************************************* 00002 * NAN - Native Abstractions for Node.js 00003 * 00004 * Copyright (c) 2016 NAN contributors 00005 * 00006 * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md> 00007 ********************************************************************/ 00008 00009 #ifndef NAN_OBJECT_WRAP_H_ 00010 #define NAN_OBJECT_WRAP_H_ 00011 00012 class ObjectWrap { 00013 public: 00014 ObjectWrap() { 00015 refs_ = 0; 00016 } 00017 00018 00019 virtual ~ObjectWrap() { 00020 if (persistent().IsEmpty()) { 00021 return; 00022 } 00023 00024 assert(persistent().IsNearDeath()); 00025 persistent().ClearWeak(); 00026 persistent().Reset(); 00027 } 00028 00029 00030 template <class T> 00031 static inline T* Unwrap(v8::Local<v8::Object> object) { 00032 assert(!object.IsEmpty()); 00033 assert(object->InternalFieldCount() > 0); 00034 // Cast to ObjectWrap before casting to T. A direct cast from void 00035 // to T won't work right when T has more than one base class. 00036 void* ptr = GetInternalFieldPointer(object, 0); 00037 ObjectWrap* wrap = static_cast<ObjectWrap*>(ptr); 00038 return static_cast<T*>(wrap); 00039 } 00040 00041 00042 inline v8::Local<v8::Object> handle() const { 00043 return New(handle_); 00044 } 00045 00046 00047 inline Persistent<v8::Object>& persistent() { 00048 return handle_; 00049 } 00050 00051 00052 protected: 00053 inline void Wrap(v8::Local<v8::Object> object) { 00054 assert(persistent().IsEmpty()); 00055 assert(object->InternalFieldCount() > 0); 00056 SetInternalFieldPointer(object, 0, this); 00057 persistent().Reset(object); 00058 MakeWeak(); 00059 } 00060 00061 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ 00062 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) 00063 00064 inline void MakeWeak() { 00065 persistent().v8::PersistentBase<v8::Object>::SetWeak( 00066 this, WeakCallback, v8::WeakCallbackType::kParameter); 00067 persistent().MarkIndependent(); 00068 } 00069 00070 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION 00071 00072 inline void MakeWeak() { 00073 persistent().v8::PersistentBase<v8::Object>::SetWeak(this, WeakCallback); 00074 persistent().MarkIndependent(); 00075 } 00076 00077 #else 00078 00079 inline void MakeWeak() { 00080 persistent().persistent.MakeWeak(this, WeakCallback); 00081 persistent().MarkIndependent(); 00082 } 00083 00084 #endif 00085 00086 /* Ref() marks the object as being attached to an event loop. 00087 * Refed objects will not be garbage collected, even if 00088 * all references are lost. 00089 */ 00090 virtual void Ref() { 00091 assert(!persistent().IsEmpty()); 00092 persistent().ClearWeak(); 00093 refs_++; 00094 } 00095 00096 /* Unref() marks an object as detached from the event loop. This is its 00097 * default state. When an object with a "weak" reference changes from 00098 * attached to detached state it will be freed. Be careful not to access 00099 * the object after making this call as it might be gone! 00100 * (A "weak reference" means an object that only has a 00101 * persistant handle.) 00102 * 00103 * DO NOT CALL THIS FROM DESTRUCTOR 00104 */ 00105 virtual void Unref() { 00106 assert(!persistent().IsEmpty()); 00107 assert(!persistent().IsWeak()); 00108 assert(refs_ > 0); 00109 if (--refs_ == 0) 00110 MakeWeak(); 00111 } 00112 00113 int refs_; // ro 00114 00115 private: 00116 NAN_DISALLOW_ASSIGN_COPY_MOVE(ObjectWrap) 00117 #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ 00118 (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) 00119 00120 static void 00121 WeakCallback(v8::WeakCallbackInfo<ObjectWrap> const& info) { 00122 ObjectWrap* wrap = info.GetParameter(); 00123 assert(wrap->refs_ == 0); 00124 assert(wrap->handle_.IsNearDeath()); 00125 wrap->handle_.Reset(); 00126 delete wrap; 00127 } 00128 00129 #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION 00130 00131 static void 00132 WeakCallback(v8::WeakCallbackData<v8::Object, ObjectWrap> const& data) { 00133 ObjectWrap* wrap = data.GetParameter(); 00134 assert(wrap->refs_ == 0); 00135 assert(wrap->handle_.IsNearDeath()); 00136 wrap->handle_.Reset(); 00137 delete wrap; 00138 } 00139 00140 #else 00141 00142 static void WeakCallback(v8::Persistent<v8::Value> value, void *data) { 00143 ObjectWrap *wrap = static_cast<ObjectWrap*>(data); 00144 assert(wrap->refs_ == 0); 00145 assert(wrap->handle_.IsNearDeath()); 00146 wrap->handle_.Reset(); 00147 delete wrap; 00148 } 00149 00150 #endif 00151 Persistent<v8::Object> handle_; 00152 }; 00153 00154 00155 #endif // NAN_OBJECT_WRAP_H_