You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							157 lines
						
					
					
						
							4.0 KiB
						
					
					
				
			
		
		
	
	
							157 lines
						
					
					
						
							4.0 KiB
						
					
					
				| /*********************************************************************
 | |
|  * 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
 | |
|    * persistant 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_
 |