| /********************************************************************* | 
|  * NAN - Native Abstractions for Node.js | 
|  * | 
|  * Copyright (c) 2018 NAN contributors | 
|  * | 
|  * MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md> | 
|  ********************************************************************/ | 
|   | 
| #ifndef NAN_WEAK_H_ | 
| #define NAN_WEAK_H_ | 
|   | 
| static const int kInternalFieldsInWeakCallback = 2; | 
| static const int kNoInternalFieldIndex = -1; | 
|   | 
| #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \ | 
|   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) | 
| # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ | 
|     v8::WeakCallbackInfo<WeakCallbackInfo<T> > const& | 
| # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ | 
|     NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ | 
| # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ | 
| # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ | 
| #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION | 
| # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ | 
|     v8::PhantomCallbackData<WeakCallbackInfo<T> > const& | 
| # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ | 
|     NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ | 
| # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ | 
| # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ | 
| #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION | 
| # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ | 
|     v8::PhantomCallbackData<WeakCallbackInfo<T> > const& | 
| # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ | 
|     v8::InternalFieldsCallbackData<WeakCallbackInfo<T>, void> const& | 
| # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ | 
| # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ | 
| #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION | 
| # define NAN_WEAK_CALLBACK_DATA_TYPE_ \ | 
|     v8::WeakCallbackData<S, WeakCallbackInfo<T> > const& | 
| # define NAN_WEAK_CALLBACK_SIG_ NAN_WEAK_CALLBACK_DATA_TYPE_ | 
| #else | 
| # define NAN_WEAK_CALLBACK_DATA_TYPE_ void * | 
| # define NAN_WEAK_CALLBACK_SIG_ \ | 
|     v8::Persistent<v8::Value>, NAN_WEAK_CALLBACK_DATA_TYPE_ | 
| #endif | 
|   | 
| template<typename T> | 
| class WeakCallbackInfo { | 
|  public: | 
|   typedef void (*Callback)(const WeakCallbackInfo<T>& data); | 
|   WeakCallbackInfo( | 
|       Persistent<v8::Value> *persistent | 
|     , Callback callback | 
|     , void *parameter | 
|     , void *field1 = 0 | 
|     , void *field2 = 0) : | 
|         callback_(callback), isolate_(0), parameter_(parameter) { | 
|     std::memcpy(&persistent_, persistent, sizeof (v8::Persistent<v8::Value>)); | 
|     internal_fields_[0] = field1; | 
|     internal_fields_[1] = field2; | 
|   } | 
|   inline v8::Isolate *GetIsolate() const { return isolate_; } | 
|   inline T *GetParameter() const { return static_cast<T*>(parameter_); } | 
|   inline void *GetInternalField(int index) const { | 
|     assert((index == 0 || index == 1) && "internal field index out of bounds"); | 
|     if (index == 0) { | 
|       return internal_fields_[0]; | 
|     } else { | 
|       return internal_fields_[1]; | 
|     } | 
|   } | 
|   | 
|  private: | 
|   NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo) | 
|   Callback callback_; | 
|   v8::Isolate *isolate_; | 
|   void *parameter_; | 
|   void *internal_fields_[kInternalFieldsInWeakCallback]; | 
|   v8::Persistent<v8::Value> persistent_; | 
|   template<typename S, typename M> friend class Persistent; | 
|   template<typename S> friend class PersistentBase; | 
| #if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION | 
| # if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION | 
|   template<typename S> | 
|   static void invoke(NAN_WEAK_CALLBACK_SIG_ data); | 
|   template<typename S> | 
|   static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data); | 
| # else | 
|   static void invoke(NAN_WEAK_CALLBACK_SIG_ data); | 
|   static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data); | 
| # endif | 
| #else | 
| # if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                     \ | 
|   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) | 
|   template<bool isFirstPass> | 
|   static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); | 
|   template<bool isFirstPass> | 
|   static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); | 
| # else | 
|   static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); | 
|   static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); | 
| # endif | 
|   static WeakCallbackInfo *unwrapparameter( | 
|       NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data); | 
|   static WeakCallbackInfo *unwraptwofield( | 
|       NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data); | 
| #endif | 
| }; | 
|   | 
|   | 
| #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \ | 
|   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) | 
|   | 
| template<typename T> | 
| template<bool isFirstPass> | 
| void | 
| WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = unwrapparameter(data); | 
|   if (isFirstPass) { | 
|     cbinfo->persistent_.Reset(); | 
|     data.SetSecondPassCallback(invokeparameter<false>); | 
|   } else { | 
|     cbinfo->callback_(*cbinfo); | 
|     delete cbinfo; | 
|   } | 
| } | 
|   | 
| template<typename T> | 
| template<bool isFirstPass> | 
| void | 
| WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = unwraptwofield(data); | 
|   if (isFirstPass) { | 
|     cbinfo->persistent_.Reset(); | 
|     data.SetSecondPassCallback(invoketwofield<false>); | 
|   } else { | 
|     cbinfo->callback_(*cbinfo); | 
|     delete cbinfo; | 
|   } | 
| } | 
|   | 
| template<typename T> | 
| WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter( | 
|     NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = | 
|       static_cast<WeakCallbackInfo<T>*>(data.GetParameter()); | 
|   cbinfo->isolate_ = data.GetIsolate(); | 
|   return cbinfo; | 
| } | 
|   | 
| template<typename T> | 
| WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield( | 
|     NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = | 
|       static_cast<WeakCallbackInfo<T>*>(data.GetInternalField(0)); | 
|   cbinfo->isolate_ = data.GetIsolate(); | 
|   return cbinfo; | 
| } | 
|   | 
| #undef NAN_WEAK_PARAMETER_CALLBACK_SIG_ | 
| #undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_ | 
| #undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ | 
| #undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ | 
| # elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION | 
|   | 
| template<typename T> | 
| void | 
| WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = unwrapparameter(data); | 
|   cbinfo->persistent_.Reset(); | 
|   cbinfo->callback_(*cbinfo); | 
|   delete cbinfo; | 
| } | 
|   | 
| template<typename T> | 
| void | 
| WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = unwraptwofield(data); | 
|   cbinfo->persistent_.Reset(); | 
|   cbinfo->callback_(*cbinfo); | 
|   delete cbinfo; | 
| } | 
|   | 
| template<typename T> | 
| WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter( | 
|     NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = | 
|        static_cast<WeakCallbackInfo<T>*>(data.GetParameter()); | 
|   cbinfo->isolate_ = data.GetIsolate(); | 
|   return cbinfo; | 
| } | 
|   | 
| template<typename T> | 
| WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield( | 
|     NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = | 
|        static_cast<WeakCallbackInfo<T>*>(data.GetInternalField1()); | 
|   cbinfo->isolate_ = data.GetIsolate(); | 
|   return cbinfo; | 
| } | 
|   | 
| #undef NAN_WEAK_PARAMETER_CALLBACK_SIG_ | 
| #undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_ | 
| #undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ | 
| #undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ | 
| #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION | 
|   | 
| template<typename T> | 
| template<typename S> | 
| void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = unwrap(data); | 
|   cbinfo->persistent_.Reset(); | 
|   cbinfo->callback_(*cbinfo); | 
|   delete cbinfo; | 
| } | 
|   | 
| template<typename T> | 
| template<typename S> | 
| WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap( | 
|     NAN_WEAK_CALLBACK_DATA_TYPE_ data) { | 
|   void *parameter = data.GetParameter(); | 
|   WeakCallbackInfo<T> *cbinfo = | 
|       static_cast<WeakCallbackInfo<T>*>(parameter); | 
|   cbinfo->isolate_ = data.GetIsolate(); | 
|   return cbinfo; | 
| } | 
|   | 
| #undef NAN_WEAK_CALLBACK_SIG_ | 
| #undef NAN_WEAK_CALLBACK_DATA_TYPE_ | 
| #else | 
|   | 
| template<typename T> | 
| void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = unwrap(data); | 
|   cbinfo->persistent_.Dispose(); | 
|   cbinfo->persistent_.Clear(); | 
|   cbinfo->callback_(*cbinfo); | 
|   delete cbinfo; | 
| } | 
|   | 
| template<typename T> | 
| WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap( | 
|     NAN_WEAK_CALLBACK_DATA_TYPE_ data) { | 
|   WeakCallbackInfo<T> *cbinfo = | 
|       static_cast<WeakCallbackInfo<T>*>(data); | 
|   cbinfo->isolate_ = v8::Isolate::GetCurrent(); | 
|   return cbinfo; | 
| } | 
|   | 
| #undef NAN_WEAK_CALLBACK_SIG_ | 
| #undef NAN_WEAK_CALLBACK_DATA_TYPE_ | 
| #endif | 
|   | 
| #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 ||                      \ | 
|   (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) | 
| template<typename T, typename M> | 
| template<typename P> | 
| inline void Persistent<T, M>::SetWeak( | 
|     P *parameter | 
|   , typename WeakCallbackInfo<P>::Callback callback | 
|   , WeakCallbackType type) { | 
|   WeakCallbackInfo<P> *wcbd; | 
|   if (type == WeakCallbackType::kParameter) { | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , parameter); | 
|     v8::PersistentBase<T>::SetWeak( | 
|         wcbd | 
|       , WeakCallbackInfo<P>::template invokeparameter<true> | 
|       , type); | 
|   } else { | 
|     v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this)); | 
|     assert((*self_v)->IsObject()); | 
|     v8::Local<v8::Object> self((*self_v).As<v8::Object>()); | 
|     int count = self->InternalFieldCount(); | 
|     void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; | 
|     for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { | 
|       internal_fields[i] = self->GetAlignedPointerFromInternalField(i); | 
|     } | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , 0 | 
|       , internal_fields[0] | 
|       , internal_fields[1]); | 
|     self->SetAlignedPointerInInternalField(0, wcbd); | 
|     v8::PersistentBase<T>::SetWeak( | 
|         static_cast<WeakCallbackInfo<P>*>(0) | 
|       , WeakCallbackInfo<P>::template invoketwofield<true> | 
|       , type); | 
|   } | 
| } | 
| #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION | 
| template<typename T, typename M> | 
| template<typename P> | 
| inline void Persistent<T, M>::SetWeak( | 
|     P *parameter | 
|   , typename WeakCallbackInfo<P>::Callback callback | 
|   , WeakCallbackType type) { | 
|   WeakCallbackInfo<P> *wcbd; | 
|   if (type == WeakCallbackType::kParameter) { | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , parameter); | 
|     v8::PersistentBase<T>::SetPhantom( | 
|         wcbd | 
|       , WeakCallbackInfo<P>::invokeparameter); | 
|   } else { | 
|     v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this)); | 
|     assert((*self_v)->IsObject()); | 
|     v8::Local<v8::Object> self((*self_v).As<v8::Object>()); | 
|     int count = self->InternalFieldCount(); | 
|     void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; | 
|     for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { | 
|       internal_fields[i] = self->GetAlignedPointerFromInternalField(i); | 
|     } | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , 0 | 
|       , internal_fields[0] | 
|       , internal_fields[1]); | 
|     self->SetAlignedPointerInInternalField(0, wcbd); | 
|     v8::PersistentBase<T>::SetPhantom( | 
|         static_cast<WeakCallbackInfo<P>*>(0) | 
|       , WeakCallbackInfo<P>::invoketwofield | 
|       , 0 | 
|       , count > 1 ? 1 : kNoInternalFieldIndex); | 
|   } | 
| } | 
| #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION | 
| template<typename T, typename M> | 
| template<typename P> | 
| inline void Persistent<T, M>::SetWeak( | 
|     P *parameter | 
|   , typename WeakCallbackInfo<P>::Callback callback | 
|   , WeakCallbackType type) { | 
|   WeakCallbackInfo<P> *wcbd; | 
|   if (type == WeakCallbackType::kParameter) { | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , parameter); | 
|     v8::PersistentBase<T>::SetPhantom( | 
|         wcbd | 
|       , WeakCallbackInfo<P>::invokeparameter); | 
|   } else { | 
|     v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this)); | 
|     assert((*self_v)->IsObject()); | 
|     v8::Local<v8::Object> self((*self_v).As<v8::Object>()); | 
|     int count = self->InternalFieldCount(); | 
|     void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; | 
|     for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { | 
|       internal_fields[i] = self->GetAlignedPointerFromInternalField(i); | 
|     } | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , 0 | 
|       , internal_fields[0] | 
|       , internal_fields[1]); | 
|     self->SetAlignedPointerInInternalField(0, wcbd); | 
|     v8::PersistentBase<T>::SetPhantom( | 
|         WeakCallbackInfo<P>::invoketwofield | 
|       , 0 | 
|       , count > 1 ? 1 : kNoInternalFieldIndex); | 
|   } | 
| } | 
| #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION | 
| template<typename T, typename M> | 
| template<typename P> | 
| inline void Persistent<T, M>::SetWeak( | 
|     P *parameter | 
|   , typename WeakCallbackInfo<P>::Callback callback | 
|   , WeakCallbackType type) { | 
|   WeakCallbackInfo<P> *wcbd; | 
|   if (type == WeakCallbackType::kParameter) { | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , parameter); | 
|     v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke); | 
|   } else { | 
|     v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this)); | 
|     assert((*self_v)->IsObject()); | 
|     v8::Local<v8::Object> self((*self_v).As<v8::Object>()); | 
|     int count = self->InternalFieldCount(); | 
|     void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; | 
|     for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { | 
|       internal_fields[i] = self->GetAlignedPointerFromInternalField(i); | 
|     } | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , 0 | 
|       , internal_fields[0] | 
|       , internal_fields[1]); | 
|     v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke); | 
|   } | 
| } | 
| #else | 
| template<typename T> | 
| template<typename P> | 
| inline void PersistentBase<T>::SetWeak( | 
|     P *parameter | 
|   , typename WeakCallbackInfo<P>::Callback callback | 
|   , WeakCallbackType type) { | 
|   WeakCallbackInfo<P> *wcbd; | 
|   if (type == WeakCallbackType::kParameter) { | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , parameter); | 
|     persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke); | 
|   } else { | 
|     v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this)); | 
|     assert((*self_v)->IsObject()); | 
|     v8::Local<v8::Object> self((*self_v).As<v8::Object>()); | 
|     int count = self->InternalFieldCount(); | 
|     void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; | 
|     for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { | 
|       internal_fields[i] = self->GetPointerFromInternalField(i); | 
|     } | 
|     wcbd = new WeakCallbackInfo<P>( | 
|         reinterpret_cast<Persistent<v8::Value>*>(this) | 
|       , callback | 
|       , 0 | 
|       , internal_fields[0] | 
|       , internal_fields[1]); | 
|     persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke); | 
|   } | 
| } | 
| #endif | 
|   | 
| #endif  // NAN_WEAK_H_ |