| /********************************************************************* | 
|  * NAN - Native Abstractions for Node.js | 
|  * | 
|  * Copyright (c) 2018 NAN contributors | 
|  * | 
|  * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md> | 
|  ********************************************************************/ | 
|   | 
| #ifndef NAN_OBJECT_WRAP_H_ | 
| #define NAN_OBJECT_WRAP_H_ | 
|   | 
| class ObjectWrap { | 
|  public: | 
|   ObjectWrap() { | 
|     refs_ = 0; | 
|   } | 
|   | 
|   | 
|   virtual ~ObjectWrap() { | 
|     if (persistent().IsEmpty()) { | 
|       return; | 
|     } | 
|   | 
|     persistent().ClearWeak(); | 
|     persistent().Reset(); | 
|   } | 
|   | 
|   | 
|   template <class T> | 
|   static inline T* Unwrap(v8::Local<v8::Object> object) { | 
|     assert(!object.IsEmpty()); | 
|     assert(object->InternalFieldCount() > 0); | 
|     // Cast to ObjectWrap before casting to T.  A direct cast from void | 
|     // to T won't work right when T has more than one base class. | 
|     void* ptr = GetInternalFieldPointer(object, 0); | 
|     ObjectWrap* wrap = static_cast<ObjectWrap*>(ptr); | 
|     return static_cast<T*>(wrap); | 
|   } | 
|   | 
|   | 
|   inline v8::Local<v8::Object> handle() const { | 
|     return New(handle_); | 
|   } | 
|   | 
|   | 
|   inline Persistent<v8::Object>& persistent() { | 
|     return handle_; | 
|   } | 
|   | 
|   | 
|  protected: | 
|   inline void Wrap(v8::Local<v8::Object> object) { | 
|     assert(persistent().IsEmpty()); | 
|     assert(object->InternalFieldCount() > 0); | 
|     SetInternalFieldPointer(object, 0, this); | 
|     persistent().Reset(object); | 
|     MakeWeak(); | 
|   } | 
|   | 
| #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \ | 
|   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) | 
|   | 
|   inline void MakeWeak() { | 
|     persistent().v8::PersistentBase<v8::Object>::SetWeak( | 
|         this, WeakCallback, v8::WeakCallbackType::kParameter); | 
| #if NODE_MAJOR_VERSION < 10 | 
|     // FIXME(bnoordhuis) Probably superfluous in older Node.js versions too. | 
|     persistent().MarkIndependent(); | 
| #endif | 
|   } | 
|   | 
| #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION | 
|   | 
|   inline void MakeWeak() { | 
|     persistent().v8::PersistentBase<v8::Object>::SetWeak(this, WeakCallback); | 
|     persistent().MarkIndependent(); | 
|   } | 
|   | 
| #else | 
|   | 
|   inline void MakeWeak() { | 
|     persistent().persistent.MakeWeak(this, WeakCallback); | 
|     persistent().MarkIndependent(); | 
|   } | 
|   | 
| #endif | 
|   | 
|   /* Ref() marks the object as being attached to an event loop. | 
|    * Refed objects will not be garbage collected, even if | 
|    * all references are lost. | 
|    */ | 
|   virtual void Ref() { | 
|     assert(!persistent().IsEmpty()); | 
|     persistent().ClearWeak(); | 
|     refs_++; | 
|   } | 
|   | 
|   /* Unref() marks an object as detached from the event loop.  This is its | 
|    * default state.  When an object with a "weak" reference changes from | 
|    * attached to detached state it will be freed. Be careful not to access | 
|    * the object after making this call as it might be gone! | 
|    * (A "weak reference" means an object that only has a | 
|    * persistent handle.) | 
|    * | 
|    * DO NOT CALL THIS FROM DESTRUCTOR | 
|    */ | 
|   virtual void Unref() { | 
|     assert(!persistent().IsEmpty()); | 
|     assert(!persistent().IsWeak()); | 
|     assert(refs_ > 0); | 
|     if (--refs_ == 0) | 
|       MakeWeak(); | 
|   } | 
|   | 
|   int refs_;  // ro | 
|   | 
|  private: | 
|   NAN_DISALLOW_ASSIGN_COPY_MOVE(ObjectWrap) | 
| #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \ | 
|   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) | 
|   | 
|   static void | 
|   WeakCallback(v8::WeakCallbackInfo<ObjectWrap> const& info) { | 
|     ObjectWrap* wrap = info.GetParameter(); | 
|     assert(wrap->refs_ == 0); | 
|     wrap->handle_.Reset(); | 
|     delete wrap; | 
|   } | 
|   | 
| #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION | 
|   | 
|   static void | 
|   WeakCallback(v8::WeakCallbackData<v8::Object, ObjectWrap> const& data) { | 
|     ObjectWrap* wrap = data.GetParameter(); | 
|     assert(wrap->refs_ == 0); | 
|     assert(wrap->handle_.IsNearDeath()); | 
|     wrap->handle_.Reset(); | 
|     delete wrap; | 
|   } | 
|   | 
| #else | 
|   | 
|   static void WeakCallback(v8::Persistent<v8::Value> value, void *data) { | 
|     ObjectWrap *wrap = static_cast<ObjectWrap*>(data); | 
|     assert(wrap->refs_ == 0); | 
|     assert(wrap->handle_.IsNearDeath()); | 
|     wrap->handle_.Reset(); | 
|     delete wrap; | 
|   } | 
|   | 
| #endif | 
|   Persistent<v8::Object> handle_; | 
| }; | 
|   | 
|   | 
| #endif  // NAN_OBJECT_WRAP_H_ |