diff --git a/nan.h b/nan.h index a5cd8955..dfc634b9 100644 --- a/nan.h +++ b/nan.h @@ -169,15 +169,12 @@ typedef v8::String::ExternalOneByteStringResource #if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) template -class NonCopyablePersistentTraits : - public v8::NonCopyablePersistentTraits {}; +class NonCopyablePersistentTraits; template -class CopyablePersistentTraits : - public v8::CopyablePersistentTraits {}; +class CopyablePersistentTraits; template -class PersistentBase : - public v8::PersistentBase {}; +class PersistentBase; template > class Persistent; diff --git a/nan_callbacks_12_inl.h b/nan_callbacks_12_inl.h index b20d68fb..a6346bd6 100644 --- a/nan_callbacks_12_inl.h +++ b/nan_callbacks_12_inl.h @@ -35,7 +35,7 @@ class ReturnValue { (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && \ (V8_MINOR_VERSION > 5 || (V8_MINOR_VERSION == 5 && \ defined(V8_BUILD_NUMBER) && V8_BUILD_NUMBER >= 8)))) - value_.Set(handle); + value_.Set(handle.persistent); #else value_.Set(*reinterpret_cast*>(&handle)); const_cast &>(handle).Reset(); diff --git a/nan_implementation_12_inl.h b/nan_implementation_12_inl.h index a140f856..edd451a5 100644 --- a/nan_implementation_12_inl.h +++ b/nan_implementation_12_inl.h @@ -393,12 +393,12 @@ inline v8::Local New(v8::Persistent const& p) { template inline v8::Local New(Persistent const& p) { - return v8::Local::New(v8::Isolate::GetCurrent(), p); + return v8::Local::New(v8::Isolate::GetCurrent(), p.persistent); } template inline v8::Local New(Global const& p) { - return v8::Local::New(v8::Isolate::GetCurrent(), p); + return v8::Local::New(v8::Isolate::GetCurrent(), p.persistent); } #endif // NAN_IMPLEMENTATION_12_INL_H_ diff --git a/nan_object_wrap.h b/nan_object_wrap.h index 0685b020..5fe57283 100644 --- a/nan_object_wrap.h +++ b/nan_object_wrap.h @@ -62,7 +62,7 @@ class ObjectWrap { (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) inline void MakeWeak() { - persistent().v8::PersistentBase::SetWeak( + persistent().persistent.v8::PersistentBase::SetWeak( this, WeakCallback, v8::WeakCallbackType::kParameter); persistent().MarkIndependent(); } @@ -70,7 +70,7 @@ class ObjectWrap { #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION inline void MakeWeak() { - persistent().v8::PersistentBase::SetWeak(this, WeakCallback); + persistent().persistent.v8::PersistentBase::SetWeak(this, WeakCallback); persistent().MarkIndependent(); } diff --git a/nan_persistent_12_inl.h b/nan_persistent_12_inl.h index f1fa193d..1c26f85b 100644 --- a/nan_persistent_12_inl.h +++ b/nan_persistent_12_inl.h @@ -9,28 +9,56 @@ #ifndef NAN_PERSISTENT_12_INL_H_ #define NAN_PERSISTENT_12_INL_H_ -template class Persistent : - public v8::Persistent { +template class PersistentBase { + v8::Persistent persistent; + + template + friend v8::Local New(const PersistentBase &p); + template + friend v8::Local New(const Persistent &p); + template + friend v8::Local New(const Global &p); + template friend class ReturnValue; + public: - NAN_INLINE Persistent() : v8::Persistent() {} + NAN_INLINE void Reset() { + persistent.Reset(); + } - template NAN_INLINE Persistent(v8::Local that) : - v8::Persistent(v8::Isolate::GetCurrent(), that) {} + template + NAN_INLINE void Reset(const v8::Local &other) { + TYPE_CHECK(T, S); + persistent.Reset(v8::Isolate::GetCurrent(), other); + } - template - NAN_INLINE Persistent(const v8::Persistent &that) : - v8::Persistent(v8::Isolate::GetCurrent(), that) {} + template + NAN_INLINE void Reset(const PersistentBase &other) { + TYPE_CHECK(T, S); + persistent.Reset(v8::Isolate::GetCurrent(), other.persistent); + } - NAN_INLINE void Reset() { v8::PersistentBase::Reset(); } + NAN_INLINE bool IsEmpty() const { return persistent.IsEmpty(); } - template - NAN_INLINE void Reset(const v8::Local &other) { - v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + NAN_INLINE void Empty() { persistent.Empty(); } + + template + NAN_INLINE bool operator==(const PersistentBase &that) { + return this->persistent == that.persistent; } - template - NAN_INLINE void Reset(const v8::PersistentBase &other) { - v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + template + NAN_INLINE bool operator==(const v8::Local &that) { + return this->persistent == that; + } + + template + NAN_INLINE bool operator!=(const PersistentBase &that) { + return !operator==(that); + } + + template + NAN_INLINE bool operator!=(const v8::Local &that) { + return !operator==(that); } template @@ -39,6 +67,90 @@ template class Persistent : , typename WeakCallbackInfo

::Callback callback , WeakCallbackType type); + NAN_INLINE void ClearWeak() { persistent.ClearWeak(); } + + NAN_INLINE void MarkIndependent() { persistent.MarkIndependent(); } + + NAN_INLINE bool IsIndependent() const { return persistent.IsIndependent(); } + + NAN_INLINE bool IsNearDeath() const { return persistent.IsNearDeath(); } + + NAN_INLINE bool IsWeak() const { return persistent.IsWeak(); } + + NAN_INLINE v8::Local Get() const { + return v8::Local::New(v8::Isolate::GetCurrent(), persistent); + } + + private: + NAN_INLINE PersistentBase() : + persistent() {} + NAN_INLINE explicit PersistentBase(v8::Persistent that) { + std::memcpy(&that, &persistent, sizeof (v8::Persistent)); + } + NAN_INLINE explicit PersistentBase(v8::Local that) : + persistent(v8::Isolate::GetCurrent(), that) { } + template friend class Persistent; + template friend class Global; + friend class ObjectWrap; +}; + +template +class NonCopyablePersistentTraits { + public: + typedef Persistent > + NonCopyablePersistent; + static const bool kResetInDestructor = false; + template + NAN_INLINE static void Copy(const Persistent &source, + NonCopyablePersistent *dest) { + Uncompilable(); + } + + template NAN_INLINE static void Uncompilable() { + TYPE_CHECK(O, v8::Primitive); + } +}; + +template +struct CopyablePersistentTraits { + typedef Persistent > CopyablePersistent; + static const bool kResetInDestructor = true; + template + static NAN_INLINE void Copy(const Persistent &source, + CopyablePersistent *dest) {} +}; + +template class Persistent : + public PersistentBase { + public: + NAN_INLINE Persistent() : PersistentBase() {} + + template NAN_INLINE Persistent(v8::Local that) : + PersistentBase(that) { + TYPE_CHECK(T, S); + } + + template + NAN_INLINE Persistent(const Persistent &that) : + PersistentBase() { + Copy(that); + } + + NAN_INLINE Persistent& operator=(const Persistent& that) { // NOLINT + Copy(that); + return *this; + } + + template + NAN_INLINE Persistent& operator=(const Persistent& that) { // NOLINT + Copy(that); + return *this; + } + + NAN_INLINE ~Persistent() { + if (M::kResetInDestructor) this->Reset(); + } + private: NAN_INLINE T *operator*() const { return *PersistentBase::persistent; } @@ -58,71 +170,97 @@ template class Persistent : #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) template -class Global : public v8::Global { +class Global : public PersistentBase { public: - NAN_INLINE Global() : v8::Global() {} - - template NAN_INLINE Global(v8::Local that) : - v8::Global(v8::Isolate::GetCurrent(), that) {} + NAN_INLINE Global() : PersistentBase() {} - template - NAN_INLINE Global(const v8::PersistentBase &that) : - v8::Global(v8::Isolate::GetCurrent(), that) {} - - NAN_INLINE void Reset() { v8::PersistentBase::Reset(); } + template + NAN_INLINE Global(v8::Local that) + : PersistentBase(that) { + TYPE_CHECK(T, S); + } - template - NAN_INLINE void Reset(const v8::Local &other) { - v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + template + NAN_INLINE Global(const PersistentBase& that) + : PersistentBase(v8::Persistent(v8::Isolate::GetCurrent(), that.persistent)) { + TYPE_CHECK(T, S); } - template - NAN_INLINE void Reset(const v8::PersistentBase &other) { - v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + NAN_INLINE Global(Global&& other) : PersistentBase(other.persistent) { + other.Empty(); } - template - NAN_INLINE void SetWeak( - P *parameter - , typename WeakCallbackInfo

::Callback callback - , WeakCallbackType type) { - reinterpret_cast*>(this)->SetWeak( - parameter, callback, type); + NAN_INLINE ~Global() { this->Reset(); } + + template + NAN_INLINE Global& operator=(Global&& rhs) { + TYPE_CHECK(T, S); + if (this != &rhs) { + std::memcpy(&rhs.persistent, &this->persistent, sizeof (v8::PersistentBase)); + rhs.Empty(); + } + return *this; } + + Global Pass() { return static_cast(*this); } + + private: + Global(Global&) = delete; + void operator=(Global&) = delete; }; #else template -class Global : public v8::UniquePersistent { - public: - NAN_INLINE Global() : v8::UniquePersistent() {} +class Global : public PersistentBase { + struct RValue { + NAN_INLINE explicit RValue(Global* obj) : object(obj) {} + Global* object; + }; - template NAN_INLINE Global(v8::Local that) : - v8::UniquePersistent(v8::Isolate::GetCurrent(), that) {} - - template - NAN_INLINE Global(const v8::PersistentBase &that) : - v8::UniquePersistent(v8::Isolate::GetCurrent(), that) {} - - NAN_INLINE void Reset() { v8::PersistentBase::Reset(); } + public: + NAN_INLINE Global() : PersistentBase() { } template - NAN_INLINE void Reset(const v8::Local &other) { - v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + NAN_INLINE Global(v8::Local that) + : PersistentBase(that) { + TYPE_CHECK(T, S); } template - NAN_INLINE void Reset(const v8::PersistentBase &other) { - v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + NAN_INLINE Global(const PersistentBase &that) + : PersistentBase(v8::Persistent(v8::Isolate::GetCurrent(), that.persistent)) { + TYPE_CHECK(T, S); } - template - NAN_INLINE void SetWeak( - P *parameter - , typename WeakCallbackInfo

::Callback callback - , WeakCallbackType type) { - reinterpret_cast*>(this)->SetWeak( - parameter, callback, type); + /** + * Move constructor. + */ + NAN_INLINE Global(RValue rvalue) + : PersistentBase(rvalue.object->persistent) { + rvalue.object->Empty(); + } + + NAN_INLINE ~Global() { this->Reset(); } + + /** + * Move via assignment. + */ + template + NAN_INLINE Global &operator=(Global rhs) { + TYPE_CHECK(T, S); + std::memcpy(&rhs.persistent, &this->persistent, sizeof (v8::Persistent)); + rhs.Empty(); + return *this; } + + /** + * Cast operator for moves. + */ + NAN_INLINE operator RValue() { return RValue(this); } + + /** + * Pass allows returning uniques from functions, etc. + */ + Global Pass() { return Global(RValue(this)); } }; #endif diff --git a/nan_persistent_pre_12_inl.h b/nan_persistent_pre_12_inl.h index 8212f583..a19da8b3 100644 --- a/nan_persistent_pre_12_inl.h +++ b/nan_persistent_pre_12_inl.h @@ -99,6 +99,10 @@ class PersistentBase { NAN_INLINE bool IsWeak() const { return persistent.IsWeak(); } + NAN_INLINE v8::Local Get() const { + return v8::Local::New(persistent); + } + private: NAN_INLINE explicit PersistentBase(v8::Persistent that) : persistent(that) { } @@ -203,7 +207,7 @@ class Global : public PersistentBase { template NAN_INLINE Global(const PersistentBase &that) - : PersistentBase(that) { + : PersistentBase(v8::Persistent::New(that.persistent)) { TYPE_CHECK(T, S); } /** @@ -211,7 +215,7 @@ class Global : public PersistentBase { */ NAN_INLINE Global(RValue rvalue) : PersistentBase(rvalue.object.persistent) { - rvalue.object->Reset(); + rvalue.object->Clear(); } NAN_INLINE ~Global() { this->Reset(); } /** @@ -220,8 +224,8 @@ class Global : public PersistentBase { template NAN_INLINE Global &operator=(Global rhs) { TYPE_CHECK(T, S); - this->Reset(rhs.persistent); - rhs.Reset(); + this->persistent = rhs.persistent; + rhs.Clear(); return *this; } /** diff --git a/nan_weak.h b/nan_weak.h index 0ea72350..11bfcdb7 100644 --- a/nan_weak.h +++ b/nan_weak.h @@ -243,9 +243,9 @@ WeakCallbackInfo *WeakCallbackInfo::unwrap( #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) -template +template template -NAN_INLINE void Persistent::SetWeak( +NAN_INLINE void PersistentBase::SetWeak( P *parameter , typename WeakCallbackInfo

::Callback callback , WeakCallbackType type) { @@ -255,7 +255,7 @@ NAN_INLINE void Persistent::SetWeak( reinterpret_cast*>(this) , callback , parameter); - v8::PersistentBase::SetWeak( + persistent.SetWeak( wcbd , WeakCallbackInfo

::invokeparameter , type); @@ -274,16 +274,16 @@ NAN_INLINE void Persistent::SetWeak( , internal_fields[0] , internal_fields[1]); (*self)->SetAlignedPointerInInternalField(0, wcbd); - v8::PersistentBase::SetWeak( + persistent.SetWeak( static_cast*>(0) , WeakCallbackInfo

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

::Callback callback , WeakCallbackType type) { @@ -293,7 +293,7 @@ NAN_INLINE void Persistent::SetWeak( reinterpret_cast*>(this) , callback , parameter); - v8::PersistentBase::SetPhantom( + persistent.SetPhantom( wcbd , WeakCallbackInfo

::invokeparameter); } else { @@ -311,7 +311,7 @@ NAN_INLINE void Persistent::SetWeak( , internal_fields[0] , internal_fields[1]); (*self)->SetAlignedPointerInInternalField(0, wcbd); - v8::PersistentBase::SetPhantom( + persistent.SetPhantom( static_cast*>(0) , WeakCallbackInfo

::invoketwofield , 0 @@ -319,9 +319,9 @@ NAN_INLINE void Persistent::SetWeak( } } #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION -template +template template -NAN_INLINE void Persistent::SetWeak( +NAN_INLINE void PersistentBase::SetWeak( P *parameter , typename WeakCallbackInfo

::Callback callback , WeakCallbackType type) { @@ -331,7 +331,7 @@ NAN_INLINE void Persistent::SetWeak( reinterpret_cast*>(this) , callback , parameter); - v8::PersistentBase::SetPhantom( + persistent.SetPhantom( wcbd , WeakCallbackInfo

::invokeparameter); } else { @@ -349,16 +349,16 @@ NAN_INLINE void Persistent::SetWeak( , internal_fields[0] , internal_fields[1]); (*self)->SetAlignedPointerInInternalField(0, wcbd); - v8::PersistentBase::SetPhantom( + persistent.SetPhantom( WeakCallbackInfo

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

::Callback callback , WeakCallbackType type) { @@ -368,7 +368,7 @@ NAN_INLINE void Persistent::SetWeak( reinterpret_cast*>(this) , callback , parameter); - v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); + persistent.SetWeak(wcbd, WeakCallbackInfo

::invoke); } else { v8::Local* self = reinterpret_cast*>(this); assert((*self)->IsObject()); @@ -383,7 +383,7 @@ NAN_INLINE void Persistent::SetWeak( , 0 , internal_fields[0] , internal_fields[1]); - v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); + persistent.SetWeak(wcbd, WeakCallbackInfo

::invoke); } } #else diff --git a/test/cpp/persistent.cpp b/test/cpp/persistent.cpp index 7a333b30..67d628bc 100644 --- a/test/cpp/persistent.cpp +++ b/test/cpp/persistent.cpp @@ -29,7 +29,7 @@ NAN_METHOD(Dispose1) { NAN_METHOD(ToPersistentAndBackAgain) { Persistent persistent(info[0].As()); - v8::Local object = New(persistent); + v8::Local object = persistent.Get(); persistent.Reset(); memset(&persistent, -1, sizeof(persistent)); // Clobber it good. info.GetReturnValue().Set(object);