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.
156 lines
4.0 KiB
156 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 |
|
* 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_
|
|
|