Skip to content

Commit

Permalink
WeakPersistent redesign
Browse files Browse the repository at this point in the history
  • Loading branch information
agnat authored and kkoopa committed May 9, 2015
1 parent 5b13d9b commit ca4de0b
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 170 deletions.
272 changes: 105 additions & 167 deletions nan.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,86 +511,6 @@ return args.GetReturnValue().Set(Nan::imp::NanEnsureHandleOrPersistent(value))
handle.Reset(v8::Isolate::GetCurrent(), obj);
}

template<typename T, typename P>
class _NanWeakCallbackData;

template<typename T, typename P>
struct _NanWeakCallbackInfo {
typedef void (*Callback)(const _NanWeakCallbackData<T, P>& data);
NAN_INLINE _NanWeakCallbackInfo(v8::Handle<T> handle, P* param, Callback cb)
: parameter(param), callback(cb) {
NanAssignPersistent(persistent, handle);
}

NAN_INLINE ~_NanWeakCallbackInfo() {
persistent.Reset();
}

P* const parameter;
Callback const callback;
v8::Persistent<T> persistent;

private:
NAN_DISALLOW_ASSIGN_COPY_MOVE(_NanWeakCallbackInfo)
};

template<typename T, typename P>
class _NanWeakCallbackData {
public:
NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo<T, P> *info)
: info_(info) { }

NAN_INLINE v8::Local<T> GetValue() const {
return NanNew(info_->persistent);
}

NAN_INLINE P* GetParameter() const { return info_->parameter; }

NAN_INLINE bool IsNearDeath() const {
return info_->persistent.IsNearDeath();
}

NAN_INLINE void Revive() const;

NAN_INLINE _NanWeakCallbackInfo<T, P>* GetCallbackInfo() const {
return info_;
}

private:
_NanWeakCallbackInfo<T, P>* info_;
};

template<typename T, typename P>
static void _NanWeakCallbackDispatcher(
const v8::WeakCallbackData<T, _NanWeakCallbackInfo<T, P> > &data) {
_NanWeakCallbackInfo<T, P> *info = data.GetParameter();
_NanWeakCallbackData<T, P> wcbd(info);
info->callback(wcbd);
if (wcbd.IsNearDeath()) {
delete wcbd.GetCallbackInfo();
}
}

template<typename T, typename P>
NAN_INLINE void _NanWeakCallbackData<T, P>::Revive() const {
info_->persistent.SetWeak(info_, &_NanWeakCallbackDispatcher<T, P>);
}

template<typename T, typename P>
NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
v8::Handle<T> handle
, P* parameter
, typename _NanWeakCallbackInfo<T, P>::Callback callback) {
_NanWeakCallbackInfo<T, P> *cbinfo =
new _NanWeakCallbackInfo<T, P>(handle, parameter, callback);
cbinfo->persistent.SetWeak(cbinfo, &_NanWeakCallbackDispatcher<T, P>);
return cbinfo;
}

# define NAN_WEAK_CALLBACK(name) \
template<typename T, typename P> \
static void name(const _NanWeakCallbackData<T, P> &data)

# define _NAN_ERROR(fun, errmsg) fun(NanNew<v8::String>(errmsg))

# define _NAN_THROW_ERROR(fun, errmsg) \
Expand Down Expand Up @@ -1004,93 +924,6 @@ NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
handle = v8::Persistent<T>::New(obj);
}

template<typename T, typename P>
class _NanWeakCallbackData;

template<typename T, typename P>
struct _NanWeakCallbackInfo {
typedef void (*Callback)(const _NanWeakCallbackData<T, P> &data);
NAN_INLINE _NanWeakCallbackInfo(v8::Handle<T> handle, P* param, Callback cb)
: parameter(param)
, callback(cb)
, persistent(v8::Persistent<T>::New(handle)) { }

NAN_INLINE ~_NanWeakCallbackInfo() {
persistent.Dispose();
persistent.Clear();
}

P* const parameter;
Callback const callback;
v8::Persistent<T> persistent;

private:
NAN_DISALLOW_ASSIGN_COPY_MOVE(_NanWeakCallbackInfo)
};

template<typename T, typename P>
class _NanWeakCallbackData {
public:
NAN_INLINE _NanWeakCallbackData(_NanWeakCallbackInfo<T, P> *info)
: info_(info) { }

NAN_INLINE v8::Local<T> GetValue() const {
return NanNew(info_->persistent);
}

NAN_INLINE P* GetParameter() const { return info_->parameter; }

NAN_INLINE bool IsNearDeath() const {
return info_->persistent.IsNearDeath();
}

NAN_INLINE void Revive() const;

NAN_INLINE _NanWeakCallbackInfo<T, P>* GetCallbackInfo() const {
return info_;
}

private:
_NanWeakCallbackInfo<T, P>* info_;
};

template<typename T, typename P>
static void _NanWeakPersistentDispatcher(
v8::Persistent<v8::Value> object, void *data) {
(void) object; // unused
_NanWeakCallbackInfo<T, P>* info =
static_cast<_NanWeakCallbackInfo<T, P>*>(data);
_NanWeakCallbackData<T, P> wcbd(info);
info->callback(wcbd);
if (wcbd.IsNearDeath()) {
delete wcbd.GetCallbackInfo();
}
}

template<typename T, typename P>
NAN_INLINE void _NanWeakCallbackData<T, P>::Revive() const {
info_->persistent.MakeWeak(
info_
, &_NanWeakPersistentDispatcher<T, P>);
}

template<typename T, typename P>
NAN_INLINE _NanWeakCallbackInfo<T, P>* NanMakeWeakPersistent(
v8::Handle<T> handle
, P* parameter
, typename _NanWeakCallbackInfo<T, P>::Callback callback) {
_NanWeakCallbackInfo<T, P> *cbinfo =
new _NanWeakCallbackInfo<T, P>(handle, parameter, callback);
cbinfo->persistent.MakeWeak(
cbinfo
, &_NanWeakPersistentDispatcher<T, P>);
return cbinfo;
}

# define NAN_WEAK_CALLBACK(name) \
template<typename T, typename P> \
static void name(const _NanWeakCallbackData<T, P> &data)

# define _NAN_ERROR(fun, errmsg) \
fun(v8::String::New(errmsg))

Expand Down Expand Up @@ -1868,6 +1701,111 @@ NAN_INLINE void NanSetInstanceTemplate(
NanSetTemplate(templ->InstanceTemplate(), name, value, attributes);
}

//=== 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);
}

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

inline
Expand Down
8 changes: 5 additions & 3 deletions test/cpp/weak.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

#include <nan.h>

NAN_WEAK_CALLBACK(weakCallback) {
void weakCallback(
NanWeakCallbackData<v8::Function, int> & data) { // NOLINT(runtime/references)
int *parameter = data.GetParameter();
NanMakeCallback(NanGetCurrentContext()->Global(), data.GetValue(), 0, NULL);
if ((*parameter)++ == 0) {
Expand All @@ -19,10 +20,11 @@ NAN_WEAK_CALLBACK(weakCallback) {
}

v8::Handle<v8::String> wrap(v8::Local<v8::Function> func) {
NanEscapableScope();
v8::Local<v8::String> lstring = NanNew<v8::String>("result");
int *parameter = new int(0);
NanMakeWeakPersistent(func, parameter, &weakCallback);
return lstring;
NanMakeWeakPersistent(func, parameter, weakCallback);
return NanEscapeScope(lstring);
}

NAN_METHOD(Hustle) {
Expand Down

0 comments on commit ca4de0b

Please sign in to comment.