/********************************************************************* * NAN - Native Abstractions for Node.js * * Copyright (c) 2016 NAN contributors * * MIT License ********************************************************************/ #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 > 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 > 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 > const& # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ v8::InternalFieldsCallbackData, 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 > 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, NAN_WEAK_CALLBACK_DATA_TYPE_ #endif template class WeakCallbackInfo { public: typedef void (*Callback)(const WeakCallbackInfo& data); WeakCallbackInfo( Persistent *persistent , Callback callback , void *parameter , void *field1 = 0 , void *field2 = 0) : callback_(callback), isolate_(0), parameter_(parameter) { std::memcpy(&persistent_, persistent, sizeof (v8::Persistent)); internal_fields_[0] = field1; internal_fields_[1] = field2; } NAN_INLINE v8::Isolate *GetIsolate() const { return isolate_; } NAN_INLINE T *GetParameter() const { return static_cast(parameter_); } NAN_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 persistent_; template friend class Persistent; template friend class PersistentBase; #if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION # if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION template static void invoke(NAN_WEAK_CALLBACK_SIG_ data); template 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 static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); 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 void WeakCallbackInfo::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { WeakCallbackInfo *cbinfo = unwrapparameter(data); if (data.IsFirstPass()) { cbinfo->persistent_.Reset(); data.SetSecondPassCallback(invokeparameter); } else { cbinfo->callback_(*cbinfo); delete cbinfo; } } template void WeakCallbackInfo::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { WeakCallbackInfo *cbinfo = unwraptwofield(data); if (data.IsFirstPass()) { cbinfo->persistent_.Reset(); data.SetSecondPassCallback(invoketwofield); } else { cbinfo->callback_(*cbinfo); delete cbinfo; } } template WeakCallbackInfo *WeakCallbackInfo::unwrapparameter( NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { WeakCallbackInfo *cbinfo = static_cast*>(data.GetParameter()); cbinfo->isolate_ = data.GetIsolate(); return cbinfo; } template WeakCallbackInfo *WeakCallbackInfo::unwraptwofield( NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { WeakCallbackInfo *cbinfo = static_cast*>(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 void WeakCallbackInfo::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { WeakCallbackInfo *cbinfo = unwrapparameter(data); cbinfo->persistent_.Reset(); cbinfo->callback_(*cbinfo); delete cbinfo; } template void WeakCallbackInfo::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { WeakCallbackInfo *cbinfo = unwraptwofield(data); cbinfo->persistent_.Reset(); cbinfo->callback_(*cbinfo); delete cbinfo; } template WeakCallbackInfo *WeakCallbackInfo::unwrapparameter( NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { WeakCallbackInfo *cbinfo = static_cast*>(data.GetParameter()); cbinfo->isolate_ = data.GetIsolate(); return cbinfo; } template WeakCallbackInfo *WeakCallbackInfo::unwraptwofield( NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { WeakCallbackInfo *cbinfo = static_cast*>(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 template void WeakCallbackInfo::invoke(NAN_WEAK_CALLBACK_SIG_ data) { WeakCallbackInfo *cbinfo = unwrap(data); cbinfo->persistent_.Reset(); cbinfo->callback_(*cbinfo); delete cbinfo; } template template WeakCallbackInfo *WeakCallbackInfo::unwrap( NAN_WEAK_CALLBACK_DATA_TYPE_ data) { void *parameter = data.GetParameter(); WeakCallbackInfo *cbinfo = static_cast*>(parameter); cbinfo->isolate_ = data.GetIsolate(); return cbinfo; } #undef NAN_WEAK_CALLBACK_SIG_ #undef NAN_WEAK_CALLBACK_DATA_TYPE_ #else template void WeakCallbackInfo::invoke(NAN_WEAK_CALLBACK_SIG_ data) { WeakCallbackInfo *cbinfo = unwrap(data); cbinfo->persistent_.Dispose(); cbinfo->persistent_.Clear(); cbinfo->callback_(*cbinfo); delete cbinfo; } template WeakCallbackInfo *WeakCallbackInfo::unwrap( NAN_WEAK_CALLBACK_DATA_TYPE_ data) { WeakCallbackInfo *cbinfo = static_cast*>(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 template NAN_INLINE void Persistent::SetWeak( P *parameter , typename WeakCallbackInfo

::Callback callback , WeakCallbackType type) { WeakCallbackInfo

*wcbd; if (type == WeakCallbackType::kParameter) { wcbd = new WeakCallbackInfo

( reinterpret_cast*>(this) , callback , parameter); v8::PersistentBase::SetWeak( wcbd , WeakCallbackInfo

::invokeparameter , type); } else { v8::Local* self = reinterpret_cast*>(this); assert((*self)->IsObject()); 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

( reinterpret_cast*>(this) , callback , 0 , internal_fields[0] , internal_fields[1]); (*self)->SetAlignedPointerInInternalField(0, wcbd); v8::PersistentBase::SetWeak( static_cast*>(0) , WeakCallbackInfo

::invoketwofield , type); } } #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION template template NAN_INLINE void Persistent::SetWeak( P *parameter , typename WeakCallbackInfo

::Callback callback , WeakCallbackType type) { WeakCallbackInfo

*wcbd; if (type == WeakCallbackType::kParameter) { wcbd = new WeakCallbackInfo

( reinterpret_cast*>(this) , callback , parameter); v8::PersistentBase::SetPhantom( wcbd , WeakCallbackInfo

::invokeparameter); } else { v8::Local* self = reinterpret_cast*>(this); assert((*self)->IsObject()); 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

( reinterpret_cast*>(this) , callback , 0 , internal_fields[0] , internal_fields[1]); (*self)->SetAlignedPointerInInternalField(0, wcbd); v8::PersistentBase::SetPhantom( static_cast*>(0) , WeakCallbackInfo

::invoketwofield , 0 , count > 1 ? 1 : kNoInternalFieldIndex); } } #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION template template NAN_INLINE void Persistent::SetWeak( P *parameter , typename WeakCallbackInfo

::Callback callback , WeakCallbackType type) { WeakCallbackInfo

*wcbd; if (type == WeakCallbackType::kParameter) { wcbd = new WeakCallbackInfo

( reinterpret_cast*>(this) , callback , parameter); v8::PersistentBase::SetPhantom( wcbd , WeakCallbackInfo

::invokeparameter); } else { v8::Local* self = reinterpret_cast*>(this); assert((*self)->IsObject()); 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

( reinterpret_cast*>(this) , callback , 0 , internal_fields[0] , internal_fields[1]); (*self)->SetAlignedPointerInInternalField(0, wcbd); v8::PersistentBase::SetPhantom( WeakCallbackInfo

::invoketwofield , 0 , count > 1 ? 1 : kNoInternalFieldIndex); } } #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION template template NAN_INLINE void Persistent::SetWeak( P *parameter , typename WeakCallbackInfo

::Callback callback , WeakCallbackType type) { WeakCallbackInfo

*wcbd; if (type == WeakCallbackType::kParameter) { wcbd = new WeakCallbackInfo

( reinterpret_cast*>(this) , callback , parameter); v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); } else { v8::Local* self = reinterpret_cast*>(this); assert((*self)->IsObject()); 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

( reinterpret_cast*>(this) , callback , 0 , internal_fields[0] , internal_fields[1]); v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); } } #else template template NAN_INLINE void PersistentBase::SetWeak( P *parameter , typename WeakCallbackInfo

::Callback callback , WeakCallbackType type) { WeakCallbackInfo

*wcbd; if (type == WeakCallbackType::kParameter) { wcbd = new WeakCallbackInfo

( reinterpret_cast*>(this) , callback , parameter); persistent.MakeWeak(wcbd, WeakCallbackInfo

::invoke); } else { v8::Local* self = reinterpret_cast*>(this); assert((*self)->IsObject()); 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

( reinterpret_cast*>(this) , callback , 0 , internal_fields[0] , internal_fields[1]); persistent.MakeWeak(wcbd, WeakCallbackInfo

::invoke); } } #endif #endif // NAN_WEAK_H_