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
			| 
								 
											4 years ago
										 
									 | 
							
								/*********************************************************************
							 | 
						||
| 
								 | 
							
								 * 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
							 | 
						||
| 
								 | 
							
								   * persistent 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_
							 |