diff --git a/.travis.yml b/.travis.yml index 953047d..4f3d5cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,15 @@ language: node_js - +env: + - CXX=g++-4.8 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 node_js: - - 0.6 - - 0.8 - - 0.10 - -notifications: - email: - - lloyd@hilaiel.com + - "0.10" + - "0.12" + - "4" + - "5" + - "6" diff --git a/README.md b/README.md index 8af5c66..a20f9ad 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ +# This project is DEPRECATED + +See https://github.com/airbnb/node-memwatch for an actively maintained fork. + + `node-memwatch`: Leak Detection and Heap Diffing for Node.JS ============================================================ -[![Build Status](https://secure.travis-ci.org/lloyd/node-memwatch.png)](http://travis-ci.org/lloyd/node-memwatch) +[![Build Status](https://travis-ci.org/deepak1556/node-memwatch.svg?branch=master)](https://travis-ci.org/deepak1556/node-memwatch) `node-memwatch` is here to help you detect and find memory leaks in Node.JS code. It provides: @@ -19,11 +24,11 @@ Node.JS code. It provides: Installation ------------ -- `npm install memwatch` +- `npm install memwatch-next` or -- `git clone git://github.com/lloyd/node-memwatch.git` +- `git clone git://github.com/marcominetti/node-memwatch.git` Description @@ -37,7 +42,7 @@ instrumentation. This module attempts to satisfy that need. To get started, import `node-memwatch` like so: ```javascript -var memwatch = require('memwatch'); +var memwatch = require('memwatch-next'); ``` ### Leak Detection @@ -63,7 +68,7 @@ The `info` object will look something like: ### Heap Usage The best way to evaluate your memory footprint is to look at heap -usage right aver V8 performs garbage collection. `memwatch` does +usage right after V8 performs garbage collection. `memwatch` does exactly this - it checks heap usage only after GC to give you a stable baseline of your actual memory usage. @@ -136,6 +141,7 @@ The contents of `diff` will look something like: } ] } +} ``` The diff shows that during the sample period, the total number of @@ -156,4 +162,4 @@ Please see the Issues to share suggestions and contribute! License ------- -http://wtfpl.org +http://wtfpl.net diff --git a/binding.gyp b/binding.gyp index 74c36b3..4581c8e 100644 --- a/binding.gyp +++ b/binding.gyp @@ -3,13 +3,14 @@ { 'target_name': 'memwatch', 'include_dirs': [ + "= 0.6.0" }, + "engines": { + "node": ">= 0.8.0" + }, "repository": { "type": "git", - "url": "https://github.com/lloyd/node-memwatch.git" + "url": "https://github.com/marcominetti/node-memwatch.git" }, "main": "include.js", - "licenses": [ { "type": "wtfpl" } ], + "licenses": [ + { + "type": "wtfpl" + } + ], "bugs": { - "url" : "https://github.com/lloyd/node-memwatch/issues" + "url": "https://github.com/marcominetti/node-memwatch/issues" }, "scripts": { "install": "node-gyp rebuild", - "test": "mocha tests" + "test": "mocha tests --reporter spec" }, "devDependencies": { - "mocha": "1.2.2", - "should": "0.6.3", - "node-gyp": "0.5.7" + "mocha": "^2.4.5", + "should": "^8.3.1" }, "contributors": [ "Jed Parsons (@jedp)", "Jeff Haynie (@jhaynie)", "Justin Matthews (@jmatthewsr-ms)" - ] + ], + "dependencies": { + "bindings": "^1.2.1", + "nan": "^2.3.2" + } } diff --git a/src/heapdiff.cc b/src/heapdiff.cc index 4055751..aeb2621 100644 --- a/src/heapdiff.cc +++ b/src/heapdiff.cc @@ -1,12 +1,6 @@ /* * 2012|lloyd|http://wtfpl.org */ - -#include "heapdiff.hh" -#include "util.hh" - -#include - #include #include #include @@ -15,6 +9,9 @@ #include // abs() #include // time() +#include "heapdiff.hh" +#include "util.hh" + using namespace v8; using namespace node; using namespace std; @@ -22,7 +19,7 @@ using namespace std; static bool s_inProgress = false; static time_t s_startTime; -bool heapdiff::HeapDiff::InProgress() +bool heapdiff::HeapDiff::InProgress() { return s_inProgress; } @@ -48,53 +45,61 @@ heapdiff::HeapDiff::~HeapDiff() void heapdiff::HeapDiff::Initialize ( v8::Handle target ) { - v8::HandleScope scope; - v8::Local t = v8::FunctionTemplate::New(New); + Nan::HandleScope scope; + + v8::Local t = Nan::New(New); t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(String::NewSymbol("HeapDiff")); + t->SetClassName(Nan::New("HeapDiff").ToLocalChecked()); - NODE_SET_PROTOTYPE_METHOD(t, "end", End); + Nan::SetPrototypeMethod(t, "end", End); - target->Set(v8::String::NewSymbol( "HeapDiff"), t->GetFunction()); + target->Set(Nan::New("HeapDiff").ToLocalChecked(), t->GetFunction()); } -v8::Handle -heapdiff::HeapDiff::New (const v8::Arguments& args) +NAN_METHOD(heapdiff::HeapDiff::New) { // Don't blow up when the caller says "new require('memwatch').HeapDiff()" // issue #30 // stolen from: https://github.com/kkaefer/node-cpp-modules/commit/bd9432026affafd8450ecfd9b49b7dc647b6d348 - if (!args.IsConstructCall()) { - return ThrowException( - Exception::TypeError( - String::New("Use the new operator to create instances of this object."))); + if (!info.IsConstructCall()) { + return Nan::ThrowTypeError("Use the new operator to create instances of this object."); } - v8::HandleScope scope; + Nan::HandleScope scope; // allocate the underlying c++ class and wrap it up in the this pointer HeapDiff * self = new HeapDiff(); - self->Wrap(args.This()); + self->Wrap(info.This()); // take a snapshot and save a pointer to it s_inProgress = true; s_startTime = time(NULL); - self->before = v8::HeapProfiler::TakeSnapshot(v8::String::New("")); + +#if (NODE_MODULE_VERSION >= 0x002D) + self->before = v8::Isolate::GetCurrent()->GetHeapProfiler()->TakeHeapSnapshot(NULL); +#else +#if (NODE_MODULE_VERSION > 0x000B) + self->before = v8::Isolate::GetCurrent()->GetHeapProfiler()->TakeHeapSnapshot(Nan::New("").ToLocalChecked(), NULL); +#else + self->before = v8::HeapProfiler::TakeSnapshot(Nan::New("").ToLocalChecked(), HeapSnapshot::kFull, NULL); +#endif +#endif + s_inProgress = false; - return args.This(); + info.GetReturnValue().Set(info.This()); } static string handleToStr(const Handle & str) { String::Utf8Value utfString(str->ToString()); - return *utfString; + return *utfString; } static void buildIDSet(set * seen, const HeapGraphNode* cur, int & s) { - v8::HandleScope scope; + Nan::HandleScope scope; // cycle detection if (seen->find(cur->GetId()) != seen->end()) { @@ -108,8 +113,11 @@ buildIDSet(set * seen, const HeapGraphNode* cur, int & s) } // update memory usage as we go +#if (NODE_MODULE_VERSION >= 0x002D) + s += cur->GetShallowSize(); +#else s += cur->GetSelfSize(); - +#endif seen->insert(cur->GetId()); for (int i=0; i < cur->GetChildrenCount(); i++) { @@ -199,7 +207,11 @@ static void manageChange(changeset & changes, const HeapGraphNode * node, bool a changeset::iterator i = changes.find(type); +#if (NODE_MODULE_VERSION >= 0x002D) + i->second.size += node->GetShallowSize() * (added ? 1 : -1); +#else i->second.size += node->GetSelfSize() * (added ? 1 : -1); +#endif if (added) i->second.added++; else i->second.released++; @@ -210,66 +222,66 @@ static void manageChange(changeset & changes, const HeapGraphNode * node, bool a static Handle changesetToObject(changeset & changes) { - v8::HandleScope scope; - Local a = Array::New(); + Nan::EscapableHandleScope scope; + Local a = Nan::New(); for (changeset::iterator i = changes.begin(); i != changes.end(); i++) { - Local d = Object::New(); - d->Set(String::New("what"), String::New(i->first.c_str())); - d->Set(String::New("size_bytes"), Integer::New(i->second.size)); - d->Set(String::New("size"), String::New(mw_util::niceSize(i->second.size).c_str())); - d->Set(String::New("+"), Integer::New(i->second.added)); - d->Set(String::New("-"), Integer::New(i->second.released)); + Local d = Nan::New(); + d->Set(Nan::New("what").ToLocalChecked(), Nan::New(i->first.c_str()).ToLocalChecked()); + d->Set(Nan::New("size_bytes").ToLocalChecked(), Nan::New(i->second.size)); + d->Set(Nan::New("size").ToLocalChecked(), Nan::New(mw_util::niceSize(i->second.size).c_str()).ToLocalChecked()); + d->Set(Nan::New("+").ToLocalChecked(), Nan::New(i->second.added)); + d->Set(Nan::New("-").ToLocalChecked(), Nan::New(i->second.released)); a->Set(a->Length(), d); } - return scope.Close(a); + return scope.Escape(a); } -static v8::Handle +static v8::Local compare(const v8::HeapSnapshot * before, const v8::HeapSnapshot * after) { - v8::HandleScope scope; + Nan::EscapableHandleScope scope; int s, diffBytes; - Local o = Object::New(); + Local o = Nan::New(); // first let's append summary information - Local b = Object::New(); - b->Set(String::New("nodes"), Integer::New(before->GetNodesCount())); - b->Set(String::New("time"), NODE_UNIXTIME_V8(s_startTime)); - o->Set(String::New("before"), b); + Local b = Nan::New(); + b->Set(Nan::New("nodes").ToLocalChecked(), Nan::New(before->GetNodesCount())); + //b->Set(Nan::New("time"), s_startTime); + o->Set(Nan::New("before").ToLocalChecked(), b); - Local a = Object::New(); - a->Set(String::New("nodes"), Integer::New(after->GetNodesCount())); - a->Set(String::New("time"), NODE_UNIXTIME_V8(time(NULL))); - o->Set(String::New("after"), a); + Local a = Nan::New(); + a->Set(Nan::New("nodes").ToLocalChecked(), Nan::New(after->GetNodesCount())); + //a->Set(Nan::New("time"), time(NULL)); + o->Set(Nan::New("after").ToLocalChecked(), a); // now let's get allocations by name set beforeIDs, afterIDs; s = 0; buildIDSet(&beforeIDs, before->GetRoot(), s); - b->Set(String::New("size_bytes"), Integer::New(s)); - b->Set(String::New("size"), String::New(mw_util::niceSize(s).c_str())); + b->Set(Nan::New("size_bytes").ToLocalChecked(), Nan::New(s)); + b->Set(Nan::New("size").ToLocalChecked(), Nan::New(mw_util::niceSize(s).c_str()).ToLocalChecked()); diffBytes = s; s = 0; buildIDSet(&afterIDs, after->GetRoot(), s); - a->Set(String::New("size_bytes"), Integer::New(s)); - a->Set(String::New("size"), String::New(mw_util::niceSize(s).c_str())); + a->Set(Nan::New("size_bytes").ToLocalChecked(), Nan::New(s)); + a->Set(Nan::New("size").ToLocalChecked(), Nan::New(mw_util::niceSize(s).c_str()).ToLocalChecked()); diffBytes = s - diffBytes; - Local c = Object::New(); - c->Set(String::New("size_bytes"), Integer::New(diffBytes)); - c->Set(String::New("size"), String::New(mw_util::niceSize(diffBytes).c_str())); - o->Set(String::New("change"), c); + Local c = Nan::New(); + c->Set(Nan::New("size_bytes").ToLocalChecked(), Nan::New(diffBytes)); + c->Set(Nan::New("size").ToLocalChecked(), Nan::New(mw_util::niceSize(diffBytes).c_str()).ToLocalChecked()); + o->Set(Nan::New("change").ToLocalChecked(), c); // before - after will reveal nodes released (memory freed) vector changedIDs; setDiff(beforeIDs, afterIDs, changedIDs); - c->Set(String::New("freed_nodes"), Integer::New(changedIDs.size())); + c->Set(Nan::New("freed_nodes").ToLocalChecked(), Nan::New(changedIDs.size())); // here's where we'll collect all the summary information changeset changes; @@ -285,42 +297,46 @@ compare(const v8::HeapSnapshot * before, const v8::HeapSnapshot * after) // after - before will reveal nodes added (memory allocated) setDiff(afterIDs, beforeIDs, changedIDs); - c->Set(String::New("allocated_nodes"), Integer::New(changedIDs.size())); + c->Set(Nan::New("allocated_nodes").ToLocalChecked(), Nan::New(changedIDs.size())); for (unsigned long i = 0; i < changedIDs.size(); i++) { const HeapGraphNode * n = after->GetNodeById(changedIDs[i]); manageChange(changes, n, true); } - c->Set(String::New("details"), changesetToObject(changes)); + c->Set(Nan::New("details").ToLocalChecked(), changesetToObject(changes)); - return scope.Close(o); + return scope.Escape(o); } -v8::Handle -heapdiff::HeapDiff::End( const Arguments& args ) +NAN_METHOD(heapdiff::HeapDiff::End) { // take another snapshot and compare them - v8::HandleScope scope; + Nan::HandleScope scope; - HeapDiff *t = Unwrap( args.This() ); + HeapDiff *t = Unwrap( info.This() ); // How shall we deal with double .end()ing? The only reasonable // approach seems to be an exception, cause nothing else makes // sense. if (t->ended) { - return v8::ThrowException( - v8::Exception::Error( - v8::String::New("attempt to end() a HeapDiff that was " - "already ended"))); + return Nan::ThrowError("attempt to end() a HeapDiff that was already ended"); } t->ended = true; s_inProgress = true; - t->after = v8::HeapProfiler::TakeSnapshot(v8::String::New("")); +#if (NODE_MODULE_VERSION >= 0x002D) + t->after = v8::Isolate::GetCurrent()->GetHeapProfiler()->TakeHeapSnapshot(NULL); +#else +#if (NODE_MODULE_VERSION > 0x000B) + t->after = v8::Isolate::GetCurrent()->GetHeapProfiler()->TakeHeapSnapshot(Nan::New("").ToLocalChecked(), NULL); +#else + t->after = v8::HeapProfiler::TakeSnapshot(Nan::New("").ToLocalChecked(), HeapSnapshot::kFull, NULL); +#endif +#endif s_inProgress = false; - v8::Handle comparison = compare(t->before, t->after); + v8::Local comparison = compare(t->before, t->after); // free early, free often. I mean, after all, this process we're in is // probably having memory problems. We want to help her. ((HeapSnapshot *) t->before)->Delete(); @@ -328,5 +344,5 @@ heapdiff::HeapDiff::End( const Arguments& args ) ((HeapSnapshot *) t->after)->Delete(); t->after = NULL; - return scope.Close(comparison); + info.GetReturnValue().Set(comparison); } diff --git a/src/heapdiff.hh b/src/heapdiff.hh index 557bbe4..917d7a6 100644 --- a/src/heapdiff.hh +++ b/src/heapdiff.hh @@ -8,16 +8,17 @@ #include #include #include +#include -namespace heapdiff +namespace heapdiff { - class HeapDiff : public node::ObjectWrap + class HeapDiff : public Nan::ObjectWrap { public: static void Initialize ( v8::Handle target ); - static v8::Handle New( const v8::Arguments& args ); - static v8::Handle End( const v8::Arguments& args ); + static NAN_METHOD(New); + static NAN_METHOD(End); static bool InProgress(); protected: diff --git a/src/init.cc b/src/init.cc index 7d289f8..36feae9 100644 --- a/src/init.cc +++ b/src/init.cc @@ -11,11 +11,11 @@ extern "C" { void init (v8::Handle target) { - v8::HandleScope scope; + Nan::HandleScope scope; heapdiff::HeapDiff::Initialize(target); - NODE_SET_METHOD(target, "upon_gc", memwatch::upon_gc); - NODE_SET_METHOD(target, "gc", memwatch::trigger_gc); + Nan::SetMethod(target, "upon_gc", memwatch::upon_gc); + Nan::SetMethod(target, "gc", memwatch::trigger_gc); v8::V8::AddGCEpilogueCallback(memwatch::after_gc); } diff --git a/src/memwatch.cc b/src/memwatch.cc index d64d544..6ebed41 100644 --- a/src/memwatch.cc +++ b/src/memwatch.cc @@ -21,7 +21,7 @@ using namespace v8; using namespace node; Handle g_context; -Handle g_cb; +Nan::Callback *g_cb; struct Baton { uv_work_t req; @@ -65,31 +65,31 @@ static struct unsigned int consecutive_growth; } s_stats; -static Handle getLeakReport(size_t heapUsage) +static Local getLeakReport(size_t heapUsage) { - HandleScope scope; + Nan::EscapableHandleScope scope; size_t growth = heapUsage - s_stats.leak_base_start; int now = time(NULL); int delta = now - s_stats.leak_time_start; - Local leakReport = Object::New(); - leakReport->Set(String::New("start"), NODE_UNIXTIME_V8(s_stats.leak_time_start)); - leakReport->Set(String::New("end"), NODE_UNIXTIME_V8(now)); - leakReport->Set(String::New("growth"), Integer::New(growth)); + Local leakReport = Nan::New(); + //leakReport->Set(Nan::New("start").ToLocalChecked(), NODE_UNIXTIME_V8(s_stats.leak_time_start)); + //leakReport->Set(Nan::New("end").ToLocalChecked(), NODE_UNIXTIME_V8(now)); + leakReport->Set(Nan::New("growth").ToLocalChecked(), Nan::New(growth)); std::stringstream ss; ss << "heap growth over 5 consecutive GCs (" << mw_util::niceDelta(delta) << ") - " << mw_util::niceSize(growth / ((double) delta / (60.0 * 60.0))) << "/hr"; - leakReport->Set(String::New("reason"), String::New(ss.str().c_str())); + leakReport->Set(Nan::New("reason").ToLocalChecked(), Nan::New(ss.str().c_str()).ToLocalChecked()); - return scope.Close(leakReport); + return scope.Escape(leakReport); } static void AsyncMemwatchAfter(uv_work_t* request) { - HandleScope scope; + Nan::HandleScope scope; Baton * b = (Baton *) request->data; @@ -120,12 +120,12 @@ static void AsyncMemwatchAfter(uv_work_t* request) { s_stats.consecutive_growth = 0; // emit a leak report! - Handle argv[3]; - argv[0] = Boolean::New(false); + Local argv[3]; + argv[0] = Nan::New(false); // the type of event to emit - argv[1] = String::New("leak"); + argv[1] = Nan::New("leak").ToLocalChecked(); argv[2] = getLeakReport(b->heapUsage); - g_cb->Call(g_context, 3, argv); + g_cb->Call(3, argv); } } else { s_stats.consecutive_growth = 0; @@ -171,37 +171,36 @@ static void AsyncMemwatchAfter(uv_work_t* request) { } // if there are any listeners, it's time to emit! - if (!g_cb.IsEmpty()) { - Handle argv[3]; + if (!g_cb->IsEmpty()) { + Local argv[3]; // magic argument to indicate to the callback all we want to know is whether there are // listeners (here we don't) - argv[0] = Boolean::New(true); - - Handle haveListeners = g_cb->Call(g_context, 1, argv); - - if (haveListeners->BooleanValue()) { - double ut= 0.0; - if (s_stats.base_ancient) { - ut = (double) ROUND(((double) (s_stats.base_recent - s_stats.base_ancient) / - (double) s_stats.base_ancient) * 1000.0) / 10.0; - } - - // ok, there are listeners, we actually must serialize and emit this stats event - Local stats = Object::New(); - stats->Set(String::New("num_full_gc"), Integer::New(s_stats.gc_full)); - stats->Set(String::New("num_inc_gc"), Integer::New(s_stats.gc_inc)); - stats->Set(String::New("heap_compactions"), Integer::New(s_stats.gc_compact)); - stats->Set(String::New("usage_trend"), Number::New(ut)); - stats->Set(String::New("estimated_base"), Integer::New(s_stats.base_recent)); - stats->Set(String::New("current_base"), Integer::New(s_stats.last_base)); - stats->Set(String::New("min"), Integer::New(s_stats.base_min)); - stats->Set(String::New("max"), Integer::New(s_stats.base_max)); - argv[0] = Boolean::New(false); - // the type of event to emit - argv[1] = String::New("stats"); - argv[2] = stats; - g_cb->Call(g_context, 3, argv); + argv[0] = Nan::New(true); + + //Handle haveListeners = g_cb->call(1, argv); + + + double ut= 0.0; + if (s_stats.base_ancient) { + ut = (double) ROUND(((double) (s_stats.base_recent - s_stats.base_ancient) / + (double) s_stats.base_ancient) * 1000.0) / 10.0; } + + // ok, there are listeners, we actually must serialize and emit this stats event + Local stats = Nan::New(); + stats->Set(Nan::New("num_full_gc").ToLocalChecked(), Nan::New(s_stats.gc_full)); + stats->Set(Nan::New("num_inc_gc").ToLocalChecked(), Nan::New(s_stats.gc_inc)); + stats->Set(Nan::New("heap_compactions").ToLocalChecked(), Nan::New(s_stats.gc_compact)); + stats->Set(Nan::New("usage_trend").ToLocalChecked(), Nan::New(ut)); + stats->Set(Nan::New("estimated_base").ToLocalChecked(), Nan::New(s_stats.base_recent)); + stats->Set(Nan::New("current_base").ToLocalChecked(), Nan::New(s_stats.last_base)); + stats->Set(Nan::New("min").ToLocalChecked(), Nan::New(s_stats.base_min)); + stats->Set(Nan::New("max").ToLocalChecked(), Nan::New(s_stats.base_max)); + argv[0] = Nan::New(false); + // the type of event to emit + argv[1] = Nan::New("stats").ToLocalChecked(); + argv[2] = stats; + g_cb->Call(3, argv); } } @@ -214,12 +213,12 @@ void memwatch::after_gc(GCType type, GCCallbackFlags flags) { if (heapdiff::HeapDiff::InProgress()) return; - HandleScope scope; + Nan::HandleScope scope; Baton * baton = new Baton; v8::HeapStatistics hs; - v8::V8::GetHeapStatistics(&hs); + Nan::GetHeapStatistics(&hs); baton->heapUsage = hs.used_heap_size(); baton->type = type; @@ -227,27 +226,34 @@ void memwatch::after_gc(GCType type, GCCallbackFlags flags) baton->req.data = (void *) baton; // schedule our work to run in a moment, once gc has fully completed. - // - // here we pass a noop work function to work around a flaw in libuv, + // + // here we pass a noop work function to work around a flaw in libuv, // uv_queue_work on unix works fine, but will will crash on - // windows. see: https://github.com/joyent/libuv/pull/629 + // windows. see: https://github.com/joyent/libuv/pull/629 uv_queue_work(uv_default_loop(), &(baton->req), noop_work_func, (uv_after_work_cb)AsyncMemwatchAfter); - - scope.Close(Undefined()); } -Handle memwatch::upon_gc(const Arguments& args) { - HandleScope scope; - if (args.Length() >= 1 && args[0]->IsFunction()) { - g_cb = Persistent::New(Handle::Cast(args[0])); - g_context = Persistent::New(Context::GetCalling()->Global()); +NAN_METHOD(memwatch::upon_gc) { + Nan::HandleScope scope; + if (info.Length() >= 1 && info[0]->IsFunction()) { + g_cb = new Nan::Callback(info[0].As()); } - return scope.Close(Undefined()); + info.GetReturnValue().Set(Nan::Undefined()); } -Handle memwatch::trigger_gc(const Arguments& args) { - HandleScope scope; - while(!V8::IdleNotification()) {}; - return scope.Close(Undefined()); +NAN_METHOD(memwatch::trigger_gc) { + Nan::HandleScope scope; + int deadline_in_ms = 500; + if (info.Length() >= 1 && info[0]->IsNumber()) { + deadline_in_ms = (int)(info[0]->Int32Value()); + } +#if (NODE_MODULE_VERSION >= 0x002D) + Nan::IdleNotification(deadline_in_ms); + Nan::LowMemoryNotification(); +#else + while(!Nan::IdleNotification(deadline_in_ms)) {}; + Nan::LowMemoryNotification(); +#endif + info.GetReturnValue().Set(Nan::Undefined()); } diff --git a/src/memwatch.hh b/src/memwatch.hh index dc3db96..73cde27 100644 --- a/src/memwatch.hh +++ b/src/memwatch.hh @@ -6,11 +6,12 @@ #define __MEMWATCH_HH #include +#include namespace memwatch { - v8::Handle upon_gc(const v8::Arguments& args); - v8::Handle trigger_gc(const v8::Arguments& args); + NAN_METHOD(upon_gc); + NAN_METHOD(trigger_gc); void after_gc(v8::GCType type, v8::GCCallbackFlags flags); }; diff --git a/src/platformcompat.hh b/src/platformcompat.hh index fb41fd5..ad49e20 100644 --- a/src/platformcompat.hh +++ b/src/platformcompat.hh @@ -1,8 +1,6 @@ #ifndef __PLATFORMCOMPAT_H #define __PLATFORMCOMPAT_H -#include // round() - #if defined(_MSC_VER) #include //isinf, isnan #include //min @@ -11,10 +9,11 @@ #define FMIN __min #define ROUND(x) floor(x + 0.5) #else -#define ISINF isinf -#define ISNAN isnan +#include // round(), isinf, isnan +#define ISINF std::isinf +#define ISNAN std::isnan #define FMIN fmin #define ROUND round #endif -#endif \ No newline at end of file +#endif diff --git a/tests.js b/tests.js index 498d752..2b8a93f 100644 --- a/tests.js +++ b/tests.js @@ -15,7 +15,7 @@ describe('the library', function() { describe('calling .gc()', function() { it('should cause a stats() event to be emitted', function(done) { memwatch.once('stats', function(s) { - s.should.be.a('object'); + s.should.be.object; done(); }); memwatch.gc();