Skip to content

Commit

Permalink
Reimplement ObjectWrap from scratch to prevent memory leaks.
Browse files Browse the repository at this point in the history
  • Loading branch information
kkoopa committed Aug 5, 2015
1 parent 5d81e51 commit 6484601
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 20 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ LINT_SOURCES = \
nan_maybe_43_inl.h \
nan_maybe_pre_43_inl.h \
nan_new.h \
nan_object_wrap.h \
nan_persistent_12_inl.h \
nan_persistent_pre_12_inl.h \
nan_string_bytes.h \
Expand Down
24 changes: 4 additions & 20 deletions nan.h
Original file line number Diff line number Diff line change
Expand Up @@ -2099,30 +2099,14 @@ inline void SetIndexedPropertyHandler(
#endif
}

//=== ObjectWrap ===============================================================

class ObjectWrap : public node::ObjectWrap {
public:
#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION
inline v8::Local<v8::Object> handle() { return New(handle_); }
inline Persistent<v8::Object> &persistent() {
Persistent<v8::Object> temp(handle_);
std::memcpy(&persistent_, &temp, sizeof(persistent_));
return persistent_;
}
private:
Persistent<v8::Object> persistent_;
#else
inline Persistent<v8::Object> &persistent() {
return static_cast<Persistent<v8::Object>&>(node::ObjectWrap::persistent());
}
#endif
};

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

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

//=== ObjectWrap ===============================================================

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

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

inline
Expand Down
102 changes: 102 additions & 0 deletions nan_object_wrap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*********************************************************************
* NAN - Native Abstractions for Node.js
*
* Copyright (c) 2015 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() {
}


template <class T>
static inline T* Unwrap(v8::Local<v8::Object> handle) {
assert(!handle.IsEmpty());
assert(handle->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(handle, 0);
ObjectWrap* wrap = static_cast<ObjectWrap*>(ptr);
return static_cast<T*>(wrap);
}


inline v8::Local<v8::Object> handle() {
return New(persistent());
}


inline Persistent<v8::Object>& persistent() {
return handle_;
}


protected:
inline void Wrap(v8::Local<v8::Object> handle) {
assert(persistent().IsEmpty());
assert(handle->InternalFieldCount() > 0);
SetInternalFieldPointer(handle, 0, this);
persistent().Reset(handle);
MakeWeak();
}


inline void MakeWeak() {
persistent().SetWeak(this, WeakCallback, WeakCallbackType::kParameter);
persistent().MarkIndependent();
}

/* 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:
static void WeakCallback(
const WeakCallbackInfo<ObjectWrap>& data) {
HandleScope scope;
ObjectWrap* wrap = data.GetParameter();
assert(wrap->refs_ == 0);
delete wrap;
}

Persistent<v8::Object> handle_;
};


#endif // NAN_OBJECT_WRAP_H_

0 comments on commit 6484601

Please sign in to comment.