| /********************************************************************* |
| * 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_ |