Skip to content

Commit

Permalink
Introduce NanPersistent
Browse files Browse the repository at this point in the history
  • Loading branch information
kkoopa committed Jul 4, 2015
1 parent b5d00a9 commit 7fed696
Show file tree
Hide file tree
Showing 22 changed files with 910 additions and 234 deletions.
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ LINT_SOURCES = \
examples/async_pi_estimate/sync.cc \
examples/async_pi_estimate/sync.h \
nan.h \
nan_string_bytes.h \
nan_implementation_12_inl.h \
nan_implementation_pre_12_inl.h \
nan_new.h \
nan_persistent_12_inl.h \
nan_persistent_pre_12_inl.h \
nan_string_bytes.h \
nan_weak.h \
test/cpp/asyncworker.cpp \
test/cpp/asyncprogressworker.cpp \
test/cpp/asyncworkererror.cpp \
Expand Down Expand Up @@ -46,6 +49,7 @@ LINT_SOURCES = \
test/cpp/symbols.cpp \
test/cpp/threadlocal.cpp \
test/cpp/weak.cpp \
test/cpp/weak2.cpp \
node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc

FILTER = -whitespace/parens
Expand All @@ -62,5 +66,7 @@ forcetest:
cd test/ && node-gyp rebuild && cd ..
npm test

$(ADDONS): nan.h nan_string_bytes.h nan_new.h nan_implementation_pre_12_inl.h nan_implementation_12_inl.h test/binding.gyp $(SOURCES)
$(ADDONS): nan.h nan_new.h nan_implementation_pre_12_inl.h nan_implementation_12_inl.h \
nan_persistent_12_inl.h nan_persistent_pre_12_inl.h nan_weak.h \
nan_string_bytes.h test/binding.gyp $(SOURCES)
cd test/ && ../node_modules/.bin/node-gyp rebuild
215 changes: 65 additions & 150 deletions nan.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@
#define ATOM_0_21_MODULE_VERSION 41
#define IOJS_1_0_MODULE_VERSION 42
#define IOJS_1_1_MODULE_VERSION 43
#define IOJS_2_0_MODULE_VERSION 44

#define TYPE_CHECK(T, S) \
while (false) { \
*(static_cast<T *volatile *>(0)) = static_cast<S*>(0); \
}

#if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION)
typedef v8::InvocationCallback NanFunctionCallback;
Expand All @@ -108,6 +114,28 @@ typedef v8::String::ExternalOneByteStringResource
NanExternalOneByteStringResource;
#endif

#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
template<typename T>
class NanNonCopyablePersistentTraits :
public v8::NonCopyablePersistentTraits<T> {};
template<typename T>
class NanCopyablePersistentTraits :
public v8::CopyablePersistentTraits<T> {};

template<typename T>
class NanPersistentBase :
public v8::PersistentBase<T> {};

template<typename T, typename M = v8::NonCopyablePersistentTraits<T> >
class NanPersistent;
#else
template<typename T> class NanNonCopyablePersistentTraits;
template<typename T> class NanPersistentBase;
template<typename T, typename P> class NanWeakCallbackData;
template<typename T, typename M = NanNonCopyablePersistentTraits<T> >
class NanPersistent;
#endif

#include "nan_new.h" // NOLINT(build/include)

// uv helpers
Expand Down Expand Up @@ -222,6 +250,27 @@ inline void nauv_key_set(nauv_key_t* key, void* value) {
template<typename T>
v8::Local<T> NanNew(v8::Handle<T>);

#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
(V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
typedef v8::WeakCallbackType NanWeakCallbackType;
#else
struct NanWeakCallbackType {
enum E {kParameter, kInternalFields};
E type;
NanWeakCallbackType(E other) : type(other) {} // NOLINT(runtime/explicit)
inline bool operator==(E other) { return other == this->type; }
inline bool operator!=(E other) { return !operator==(other); }
};
#endif

template<typename P> class NanWeakCallbackInfo;

#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
# include "nan_persistent_12_inl.h" // NOLINT(build/include)
#else
# include "nan_persistent_pre_12_inl.h" // NOLINT(build/include)
#endif

namespace Nan { namespace imp {
template<typename T>
NAN_INLINE v8::Persistent<T> &NanEnsureHandleOrPersistent(
Expand Down Expand Up @@ -535,20 +584,6 @@ class NanEscapableScope {
v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics);
}

template<typename T>
NAN_INLINE void NanAssignPersistent(
v8::Persistent<T>& handle
, v8::Handle<T> obj) {
handle.Reset(v8::Isolate::GetCurrent(), obj);
}

template<typename T>
NAN_INLINE void NanAssignPersistent(
v8::Persistent<T>& handle
, const v8::Persistent<T>& obj) {
handle.Reset(v8::Isolate::GetCurrent(), obj);
}

# define X(NAME) \
NAN_INLINE v8::Local<v8::Value> Nan ## NAME(const char *errmsg) { \
NanEscapableScope scope; \
Expand Down Expand Up @@ -584,12 +619,6 @@ class NanEscapableScope {
v8::Isolate::GetCurrent()->ThrowException(error);
}

template<typename T> NAN_INLINE void NanDisposePersistent(
v8::Persistent<T> &handle
) {
handle.Reset();
}

NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
char *data
, size_t length
Expand Down Expand Up @@ -934,14 +963,6 @@ class NanEscapableScope {
v8::V8::GetHeapStatistics(heap_statistics);
}

template<typename T>
NAN_INLINE void NanAssignPersistent(
v8::Persistent<T>& handle
, v8::Handle<T> obj) {
handle.Dispose();
handle = v8::Persistent<T>::New(obj);
}

# define X(NAME) \
NAN_INLINE v8::Local<v8::Value> Nan ## NAME(const char *errmsg) { \
NanEscapableScope scope; \
Expand Down Expand Up @@ -979,13 +1000,6 @@ class NanEscapableScope {
return scope.Escape(v8::Local<v8::Value>::New(v8::ThrowException(error)));
}

template<typename T>
NAN_INLINE void NanDisposePersistent(
v8::Persistent<T> &handle) { // NOLINT(runtime/references)
handle.Dispose();
handle.Clear();
}

NAN_INLINE v8::Local<v8::Object> NanNewBufferHandle (
char *data
, size_t length
Expand Down Expand Up @@ -1242,19 +1256,19 @@ class NanCallback {
NanCallback() {
NanScope scope;
v8::Local<v8::Object> obj = NanNew<v8::Object>();
NanAssignPersistent(handle, obj);
handle.Reset(obj);
}

explicit NanCallback(const v8::Handle<v8::Function> &fn) {
NanScope scope;
v8::Local<v8::Object> obj = NanNew<v8::Object>();
NanAssignPersistent(handle, obj);
handle.Reset(obj);
SetFunction(fn);
}

~NanCallback() {
if (handle.IsEmpty()) return;
NanDisposePersistent(handle);
handle.Reset();
}

bool operator==(const NanCallback &other) const {
Expand Down Expand Up @@ -1324,7 +1338,7 @@ class NanCallback {

private:
NAN_DISALLOW_ASSIGN_COPY_MOVE(NanCallback)
v8::Persistent<v8::Object> handle;
NanPersistent<v8::Object> handle;
static const uint32_t kCallbackIndex = 0;

#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION)
Expand All @@ -1350,7 +1364,7 @@ class NanCallback {
, v8::Handle<v8::Value> argv[]) const {
NanEscapableScope scope;

v8::Local<v8::Function> callback = handle->
v8::Local<v8::Function> callback = NanNew(handle)->
Get(kCallbackIndex).As<v8::Function>();
return scope.Escape(Nan::imp::NanEnsureLocal(node::MakeCallback(
target
Expand All @@ -1370,14 +1384,14 @@ class NanCallback {

NanScope scope;
v8::Local<v8::Object> obj = NanNew<v8::Object>();
NanAssignPersistent(persistentHandle, obj);
persistentHandle.Reset(obj);
}

virtual ~NanAsyncWorker() {
NanScope scope;

if (!persistentHandle.IsEmpty())
NanDisposePersistent(persistentHandle);
persistentHandle.Reset();
if (callback)
delete callback;
if (errmsg_)
Expand Down Expand Up @@ -1438,7 +1452,7 @@ class NanCallback {
}

protected:
v8::Persistent<v8::Object> persistentHandle;
NanPersistent<v8::Object> persistentHandle;
NanCallback *callback;

virtual void HandleOKCallback() {
Expand Down Expand Up @@ -1746,114 +1760,13 @@ class NanObjectWrap : public node::ObjectWrap {

//=== Weak Persistent Handling =================================================

#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION
# define NAN_WEAK_CALLBACK_DATA_TYPE_ \
v8::WeakCallbackData<T, NanWeakCallbackData<T, P> > 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, typename P>
class NanWeakCallbackData {
public: // constructors
typedef void (*Callback)(
NanWeakCallbackData & data // NOLINT(runtime/references)
);
NanWeakCallbackData(v8::Handle<T> handle, P* param, Callback cb)
: parameter(param), callback(cb) {
NanAssignPersistent(persistent, handle);
Revive();
}
inline ~NanWeakCallbackData();

public: // member functions
v8::Local<T> GetValue() const { return NanNew(persistent); }
v8::Persistent<T> &GetPersistent() const { return persistent; }
P* GetParameter() const { return parameter; }
bool IsNearDeath() const { return persistent.IsNearDeath(); }
inline void Revive();

private: // constructors
NAN_DISALLOW_ASSIGN_COPY_MOVE(NanWeakCallbackData)

private: // static member functions
static
void
invoke(NAN_WEAK_CALLBACK_SIG_ data) {
NanWeakCallbackData * wcbd = unwrap(data);
wcbd->callback(*wcbd);
if (wcbd->IsNearDeath()) {
delete wcbd;
}
}

static inline
NanWeakCallbackData *
unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);

private: // data members
P* const parameter;
Callback const callback;
v8::Persistent<T> persistent;
};

#undef NAN_WEAK_CALLBACK_DATA_TYPE_
#undef NAN_WEAK_CALLBACK_SIG_

#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION

template <typename T, typename P>
NanWeakCallbackData<T, P>::~NanWeakCallbackData() { persistent.Reset(); }

template <typename T, typename P>
void
NanWeakCallbackData<T, P>::Revive() { persistent.SetWeak(this, &invoke); }

template <typename T, typename P>
NanWeakCallbackData<T, P> *
NanWeakCallbackData<T, P>::unwrap(
v8::WeakCallbackData<T, NanWeakCallbackData> const& data) {
return data.GetParameter();
}

#else

template <typename T, typename P>
NanWeakCallbackData<T, P>::~NanWeakCallbackData() {
persistent.Dispose();
persistent.Clear();
}

template <typename T, typename P>
void
NanWeakCallbackData<T, P>::Revive() { persistent.MakeWeak(this, &invoke); }

template <typename T, typename P>
NanWeakCallbackData<T, P> *
NanWeakCallbackData<T, P>::unwrap(void * data) {
return static_cast<NanWeakCallbackData*>(data);
}

#endif

template<typename T, typename P>
inline
NanWeakCallbackData<T, P>*
NanMakeWeakPersistent(
v8::Handle<T> handle
, P* parameter
, typename NanWeakCallbackData<T, P>::Callback callback) {
return new NanWeakCallbackData<T, P>(handle, parameter, callback);
}
#include "nan_weak.h" // NOLINT(build/include)

//=== Export ==================================================================

inline
void
NanExport(v8::Handle<v8::Object> target, const char * name,
NanExport(v8::Handle<v8::Object> target, const char *name,
NanFunctionCallback f) {
target->Set(NanNew<v8::String>(name),
NanNew<v8::FunctionTemplate>(f)->GetFunction());
Expand All @@ -1863,25 +1776,25 @@ NanExport(v8::Handle<v8::Object> target, const char * name,

struct NanTap {
explicit NanTap(v8::Handle<v8::Value> t) : t_() {
NanAssignPersistent(t_, t->ToObject());
t_.Reset(t->ToObject());
}

~NanTap() { NanDisposePersistent(t_); } // not sure if neccessary
~NanTap() { t_.Reset(); } // not sure if neccessary

inline void plan(int i) {
v8::Handle<v8::Value> arg = NanNew(i);
NanMakeCallback(NanNew(t_), "plan", 1, &arg);
}

inline void ok(bool isOk, const char * msg = NULL) {
inline void ok(bool isOk, const char *msg = NULL) {
v8::Handle<v8::Value> args[2];
args[0] = NanNew(isOk);
if (msg) args[1] = NanNew(msg);
NanMakeCallback(NanNew(t_), "ok", msg ? 2 : 1, args);
}

private:
v8::Persistent<v8::Object> t_;
NanPersistent<v8::Object> t_;
};

#define NAN_STRINGIZE2(x) #x
Expand All @@ -1893,4 +1806,6 @@ struct NanTap {
#define return_NanUndefined() NanReturnUndefined()
#define NAN_EXPORT(target, function) NanExport(target, #function, function)

#undef TYPE_CHECK

#endif // NAN_H_

0 comments on commit 7fed696

Please sign in to comment.