[Pkg-javascript-commits] [node-leveldown] 370/492: initial 0.11 compatibility attempt, using NAN

Andrew Kelley andrewrk-guest at moszumanska.debian.org
Sun Jul 6 17:14:18 UTC 2014


This is an automated email from the git hooks/post-receive script.

andrewrk-guest pushed a commit to annotated tag rocksdb-0.10.1
in repository node-leveldown.

commit d4ed0d6a6237a4d9f0a485bf9cdc8634cbf6abed
Author: Rod Vagg <rod at vagg.org>
Date:   Sat Jul 20 21:14:25 2013 +1000

    initial 0.11 compatibility attempt, using NAN
---
 binding.gyp            |   3 +-
 src/async.cc           |  73 ----------
 src/async.h            |  31 ++--
 src/batch.cc           | 128 ++++++----------
 src/batch.h            |  14 +-
 src/batch_async.cc     |   4 +-
 src/batch_async.h      |   3 +-
 src/database.cc        | 387 +++++++++++++++++++++----------------------------
 src/database.h         |  61 ++++----
 src/database_async.cc  | 107 +++++++-------
 src/database_async.h   |  54 ++++---
 src/iterator.cc        | 149 ++++++++++---------
 src/iterator.h         |  33 ++---
 src/iterator_async.cc  |  19 ++-
 src/iterator_async.h   |   5 +-
 src/leveldown.cc       |  52 +++----
 src/leveldown.h        | 118 +++------------
 src/leveldown_async.cc |   8 +-
 src/leveldown_async.h  |   4 +-
 src/nan.h              |   1 +
 20 files changed, 499 insertions(+), 755 deletions(-)

diff --git a/binding.gyp b/binding.gyp
index 6c20da5..ddbd534 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -20,8 +20,7 @@
             "<(module_root_dir)/deps/leveldb/leveldb.gyp:leveldb"
         ]
       , "sources": [
-            "src/async.cc"
-          , "src/batch.cc"
+            "src/batch.cc"
           , "src/batch_async.cc"
           , "src/database.cc"
           , "src/database_async.cc"
diff --git a/src/async.cc b/src/async.cc
deleted file mode 100644
index 45c90c5..0000000
--- a/src/async.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (c) 2012-2013 LevelDOWN contributors
- * See list at <https://github.com/rvagg/node-leveldown#contributing>
- * MIT +no-false-attribs License <https://github.com/rvagg/node-leveldown/blob/master/LICENSE>
- */
-
-#include <node.h>
-
-#include "database.h"
-#include "leveldown.h"
-#include "async.h"
-
-namespace leveldown {
-
-/** ASYNC BASE **/
-
-AsyncWorker::AsyncWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
-) : database(database)
-  , callback(callback)
-{
-    request.data = this;
-};
-
-AsyncWorker::~AsyncWorker () {}
-
-void AsyncWorker::WorkComplete () {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
-
-  if (status.ok())
-    HandleOKCallback();
-  else
-    HandleErrorCallback();
-  callback.Dispose(LD_NODE_ISOLATE);
-}
-
-void AsyncWorker::HandleOKCallback () {
-  LD_RUN_CALLBACK(callback, NULL, 0);  
-}
-
-void AsyncWorker::HandleErrorCallback () {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
-
-  v8::Local<v8::Value> argv[] = {
-      v8::Local<v8::Value>::New(
-        v8::Exception::Error(v8::String::New(status.ToString().c_str()))
-      )
-  };
-  LD_RUN_CALLBACK(callback, argv, 1);
-}
-
-void AsyncExecute (uv_work_t* req) {
-  static_cast<AsyncWorker*>(req->data)->Execute();
-}
-
-void AsyncExecuteComplete (uv_work_t* req) {
-  AsyncWorker* worker = static_cast<AsyncWorker*>(req->data);
-  worker->WorkComplete();
-  delete worker;
-}
-
-void AsyncQueueWorker (AsyncWorker* worker) {
-  uv_queue_work(
-      uv_default_loop()
-    , &worker->request
-    , AsyncExecute
-    , (uv_after_work_cb)AsyncExecuteComplete
-  );
-}
-
-} // namespace leveldown
diff --git a/src/async.h b/src/async.h
index dc1b1e6..64646df 100644
--- a/src/async.h
+++ b/src/async.h
@@ -7,34 +7,35 @@
 #define LD_ASYNC_H
 
 #include <node.h>
+#include "nan.h"
 #include "database.h"
 
 namespace leveldown {
 
-/* abstract */ class AsyncWorker {
+class Database;
+
+/* abstract */ class AsyncWorker : public NanAsyncWorker {
 public:
   AsyncWorker (
       leveldown::Database* database
-    , v8::Persistent<v8::Function> callback
-  );
-
-  virtual ~AsyncWorker ();
-  uv_work_t request;
-  virtual void WorkComplete ();
-  virtual void Execute () =0;
+    , NanCallback *callback
+  ) : NanAsyncWorker(callback), database(database) {
+    NanScope();
+    v8::Local<v8::Object> obj = v8::Object::New();
+    NanAssignPersistent(v8::Object, persistentHandle, obj);
+  }
 
 protected:
+  void SetStatus(leveldb::Status status) {
+    this->status = status;
+    if (!status.ok())
+      this->errmsg = status.ToString().c_str();
+  }
   Database* database;
-  v8::Persistent<v8::Function> callback;
+private:
   leveldb::Status status;
-  virtual void HandleOKCallback ();
-  virtual void HandleErrorCallback ();
 };
 
-void AsyncExecute (uv_work_t* req);
-void AsyncExecuteComplete (uv_work_t* req);
-void AsyncQueueWorker (AsyncWorker* worker);
-
 } // namespace leveldown
 
 #endif
diff --git a/src/batch.cc b/src/batch.cc
index 3e68a52..695dcb1 100644
--- a/src/batch.cc
+++ b/src/batch.cc
@@ -1,19 +1,21 @@
 #include <node.h>
 #include <node_buffer.h>
 
+
+#include "nan.h"
 #include "database.h"
 #include "batch_async.h"
 #include "batch.h"
 
 namespace leveldown {
 
-v8::Persistent<v8::Function> Batch::constructor;
+static v8::Persistent<v8::FunctionTemplate> batch_constructor;
 
 Batch::Batch (leveldown::Database* database, bool sync) : database(database) {
   options = new leveldb::WriteOptions();
   options->sync = sync;
   batch = new leveldb::WriteBatch();
-  references = new std::vector<Reference>;
+  references = new std::vector<Reference *>;
   hasData = false;
   written = false;
 }
@@ -29,34 +31,18 @@ leveldb::Status Batch::Write () {
 }
 
 void Batch::Init () {
-  LD_NODE_ISOLATE_DECL
   v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(Batch::New);
-  tpl->SetClassName(v8::String::NewSymbol("Batch"));
+  NanAssignPersistent(v8::FunctionTemplate, batch_constructor, tpl);
+  tpl->SetClassName(NanSymbol("Batch"));
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("put")
-    , v8::FunctionTemplate::New(Batch::Put)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("del")
-    , v8::FunctionTemplate::New(Batch::Del)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("clear")
-    , v8::FunctionTemplate::New(Batch::Clear)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("write")
-    , v8::FunctionTemplate::New(Batch::Write)->GetFunction()
-  );
-  constructor = v8::Persistent<v8::Function>::New(
-      LD_NODE_ISOLATE_PRE
-      tpl->GetFunction());
+  NODE_SET_PROTOTYPE_METHOD(tpl, "put", Batch::Put);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "del", Batch::Del);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "clear", Batch::Clear);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "write", Batch::Write);
 }
 
-v8::Handle<v8::Value> Batch::New (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Batch::New) {
+  NanScope();
 
   Database* database = node::ObjectWrap::Unwrap<Database>(args[0]->ToObject());
   v8::Local<v8::Object> optionsObj;
@@ -65,12 +51,12 @@ v8::Handle<v8::Value> Batch::New (const v8::Arguments& args) {
     optionsObj = v8::Local<v8::Object>::Cast(args[1]);
   }
 
-  bool sync = BooleanOptionValue(optionsObj, option_sync);
+  bool sync = NanBooleanOptionValue(optionsObj, NanSymbol("sync"));
 
   Batch* batch = new Batch(database, sync);
   batch->Wrap(args.This());
 
-  return args.This();
+  NanReturnValue(args.This());
 }
 
 v8::Handle<v8::Value> Batch::NewInstance (
@@ -78,31 +64,31 @@ v8::Handle<v8::Value> Batch::NewInstance (
       , v8::Handle<v8::Object> optionsObj
     ) {
 
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+  NanScope();
 
   v8::Local<v8::Object> instance;
 
+  v8::Local<v8::FunctionTemplate> constructorHandle =
+      NanPersistentToLocal(batch_constructor);
+
   if (optionsObj.IsEmpty()) {
     v8::Handle<v8::Value> argv[1] = { database };
-    instance = constructor->NewInstance(1, argv);
+    instance = constructorHandle->GetFunction()->NewInstance(1, argv);
   } else {
     v8::Handle<v8::Value> argv[2] = { database, optionsObj };
-    instance = constructor->NewInstance(2, argv);
+    instance = constructorHandle->GetFunction()->NewInstance(2, argv);
   }
 
   return scope.Close(instance);
 }
 
-v8::Handle<v8::Value> Batch::Put (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Batch::Put) {
+  NanScope();
 
   Batch* batch = ObjectWrap::Unwrap<Batch>(args.Holder());
 
-  if (batch->written) {
-    LD_THROW_RETURN(write() already called on this batch)
-  }
+  if (batch->written)
+    return NanThrowError("write() already called on this batch");
 
   v8::Handle<v8::Function> callback; // purely for the error macros
 
@@ -114,31 +100,23 @@ v8::Handle<v8::Value> Batch::Put (const v8::Arguments& args) {
   LD_STRING_OR_BUFFER_TO_SLICE(key, keyBuffer, key)
   LD_STRING_OR_BUFFER_TO_SLICE(value, valueBuffer, value)
 
-  batch->references->push_back(Reference(
-      v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE keyBuffer)
-    , key
-  ));
-  batch->references->push_back(Reference(
-      v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE valueBuffer)
-    , value
-  ));
+  batch->references->push_back(new Reference(keyBuffer, key));
+  batch->references->push_back(new Reference(valueBuffer, value));
 
   batch->batch->Put(key, value);
   if (!batch->hasData)
     batch->hasData = true;
 
-  return scope.Close(args.Holder());
+  NanReturnValue(args.Holder());
 }
 
-v8::Handle<v8::Value> Batch::Del (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Batch::Del) {
+  NanScope();
 
   Batch* batch = ObjectWrap::Unwrap<Batch>(args.Holder());
 
-  if (batch->written) {
-    LD_THROW_RETURN(write() already called on this batch)
-  }
+  if (batch->written)
+    return NanThrowError("write() already called on this batch");
 
   v8::Handle<v8::Function> callback; // purely for the error macros
 
@@ -147,62 +125,52 @@ v8::Handle<v8::Value> Batch::Del (const v8::Arguments& args) {
   v8::Local<v8::Value> keyBuffer = args[0];
   LD_STRING_OR_BUFFER_TO_SLICE(key, keyBuffer, key)
 
-  batch->references->push_back(Reference(
-      v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE keyBuffer)
-    , key
-  ));
+  batch->references->push_back(new Reference(keyBuffer, key));
 
   batch->batch->Delete(key);
   if (!batch->hasData)
     batch->hasData = true;
 
-  return scope.Close(args.Holder());
+  NanReturnValue(args.Holder());
 }
 
-v8::Handle<v8::Value> Batch::Clear (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Batch::Clear) {
+  NanScope();
 
   Batch* batch = ObjectWrap::Unwrap<Batch>(args.Holder());
 
-  if (batch->written) {
-    LD_THROW_RETURN(write() already called on this batch)
-  }
+  if (batch->written)
+    return NanThrowError("write() already called on this batch");
 
   batch->batch->Clear();
   batch->hasData = false;
 
-  return scope.Close(args.Holder());
+  NanReturnValue(args.Holder());
 }
 
-v8::Handle<v8::Value> Batch::Write (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Batch::Write) {
+  NanScope();
 
   Batch* batch = ObjectWrap::Unwrap<Batch>(args.Holder());
 
-  if (batch->written) {
-    LD_THROW_RETURN(write() already called on this batch)
-  }
+  if (batch->written)
+    return NanThrowError("write() already called on this batch");
   
-  if (args.Length() == 0) {
-    LD_THROW_RETURN(write() requires a callback argument)
-  }
+  if (args.Length() == 0)
+    return NanThrowError("write() requires a callback argument");
 
   batch->written = true;
 
   if (batch->hasData) {
-    v8::Persistent<v8::Function> callback = v8::Persistent<v8::Function>::New(
-        LD_NODE_ISOLATE_PRE
-        v8::Local<v8::Function>::Cast(args[0]));
-
+    NanCallback *callback =
+        new NanCallback(v8::Local<v8::Function>::Cast(args[0]));
     BatchWriteWorker* worker  = new BatchWriteWorker(batch, callback);
-    AsyncQueueWorker(worker);
+    NanAsyncQueueWorker(worker);
   } else {
     LD_RUN_CALLBACK(v8::Local<v8::Function>::Cast(args[0]), NULL, 0);
   }
 
-  return v8::Undefined();
+  NanReturnUndefined();
 }
 
 } // namespace leveldown
diff --git a/src/batch.h b/src/batch.h
index 31f1f04..7716d88 100644
--- a/src/batch.h
+++ b/src/batch.h
@@ -26,17 +26,15 @@ private:
   leveldown::Database* database;
   leveldb::WriteOptions* options;
   leveldb::WriteBatch* batch;
-  std::vector<Reference>* references;
+  std::vector<Reference *>* references;
   bool hasData; // keep track of whether we're writing data or not
   bool written;
 
-  static v8::Persistent<v8::Function> constructor;
-
-  LD_V8_METHOD( New   )
-  LD_V8_METHOD( Put   )
-  LD_V8_METHOD( Del   )
-  LD_V8_METHOD( Clear )
-  LD_V8_METHOD( Write )
+  static NAN_METHOD(New);
+  static NAN_METHOD(Put);
+  static NAN_METHOD(Del);
+  static NAN_METHOD(Clear);
+  static NAN_METHOD(Write);
 };
 
 } // namespace leveldown
diff --git a/src/batch_async.cc b/src/batch_async.cc
index 93f34e1..4ff256c 100644
--- a/src/batch_async.cc
+++ b/src/batch_async.cc
@@ -14,7 +14,7 @@ namespace leveldown {
 
 BatchWriteWorker::BatchWriteWorker (
     Batch* batch
-  , v8::Persistent<v8::Function> callback
+  , NanCallback *callback
 ) : AsyncWorker(NULL, callback)
   , batch(batch)
 {};
@@ -22,7 +22,7 @@ BatchWriteWorker::BatchWriteWorker (
 BatchWriteWorker::~BatchWriteWorker () {}
 
 void BatchWriteWorker::Execute () {
-  status = batch->Write();
+  SetStatus(batch->Write());
 }
 
 } // namespace leveldown
diff --git a/src/batch_async.h b/src/batch_async.h
index 46e459b..05fb4ad 100644
--- a/src/batch_async.h
+++ b/src/batch_async.h
@@ -8,6 +8,7 @@
 
 #include <node.h>
 
+#include "nan.h"
 #include "async.h"
 #include "batch.h"
 #include "database.h"
@@ -18,7 +19,7 @@ class BatchWriteWorker : public AsyncWorker {
 public:
   BatchWriteWorker (
       Batch* batch
-    , v8::Persistent<v8::Function> callback
+    , NanCallback *callback
   );
 
   virtual ~BatchWriteWorker ();
diff --git a/src/database.cc b/src/database.cc
index 7f0bd10..8424048 100644
--- a/src/database.cc
+++ b/src/database.cc
@@ -19,6 +19,8 @@
 
 namespace leveldown {
 
+static v8::Persistent<v8::FunctionTemplate> database_constructor;
+
 Database::Database (char* location) : location(location) {
   db = NULL;
   currentIteratorId = 0;
@@ -105,7 +107,7 @@ void Database::ReleaseIterator (uint32_t id) {
   // iterators to end before we can close them
   iterators.erase(id);
   if (iterators.size() == 0 && pendingCloseWorker != NULL) {
-    AsyncQueueWorker((AsyncWorker*)pendingCloseWorker);
+    NanAsyncQueueWorker((AsyncWorker*)pendingCloseWorker);
     pendingCloseWorker = NULL;
   }
 }
@@ -117,139 +119,109 @@ void Database::CloseDatabase () {
 
 /* V8 exposed functions *****************************/
 
-v8::Persistent<v8::Function> Database::constructor;
-
-v8::Handle<v8::Value> LevelDOWN (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(LevelDOWN) {
+  NanScope();
 
-  return scope.Close(Database::NewInstance(args));
+  v8::Local<v8::String> location;
+  if (args.Length() != 0 && args[0]->IsString())
+    location = args[0].As<v8::String>();
+  NanReturnValue(Database::NewInstance(location));
 }
 
 void Database::Init () {
-  LD_NODE_ISOLATE_DECL
-  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(New);
-  tpl->SetClassName(v8::String::NewSymbol("Database"));
+  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(Database::New);
+  NanAssignPersistent(v8::FunctionTemplate, database_constructor, tpl);
+  tpl->SetClassName(NanSymbol("Database"));
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("open")
-    , v8::FunctionTemplate::New(Open)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("close")
-    , v8::FunctionTemplate::New(Close)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("put")
-    , v8::FunctionTemplate::New(Put)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("get")
-    , v8::FunctionTemplate::New(Get)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("del")
-    , v8::FunctionTemplate::New(Delete)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("batch")
-    , v8::FunctionTemplate::New(Batch)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("approximateSize")
-    , v8::FunctionTemplate::New(ApproximateSize)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("getProperty")
-    , v8::FunctionTemplate::New(GetProperty)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("iterator")
-    , v8::FunctionTemplate::New(Iterator)->GetFunction()
-  );
-  constructor = v8::Persistent<v8::Function>::New(
-      LD_NODE_ISOLATE_PRE
-      tpl->GetFunction());
+  NODE_SET_PROTOTYPE_METHOD(tpl, "open", Database::Open);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "close", Database::Close);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "put", Database::Put);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "get", Database::Get);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "del", Database::Delete);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "batch", Database::Batch);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "approximateSize", Database::ApproximateSize);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "getProperty", Database::GetProperty);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "iterator", Database::Iterator);
 }
 
-v8::Handle<v8::Value> Database::New (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::New) {
+  NanScope();
 
-  if (args.Length() == 0) {
-    LD_THROW_RETURN(constructor requires at least a location argument)
-  }
+  if (args.Length() == 0)
+    return NanThrowError("constructor requires at least a location argument");
 
-  if (!args[0]->IsString()) {
-    LD_THROW_RETURN(constructor requires a location string argument)
-  }
+  if (!args[0]->IsString())
+    return NanThrowError("constructor requires a location string argument");
 
-  char* location = FromV8String(args[0]);
+  char* location = NanFromV8String(args[0]);
 
   Database* obj = new Database(location);
   obj->Wrap(args.This());
 
-  return args.This();
+  NanReturnValue(args.This());
 }
 
-v8::Handle<v8::Value> Database::NewInstance (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+v8::Handle<v8::Value> Database::NewInstance (v8::Local<v8::String> &location) {
+  NanScope();
 
   v8::Local<v8::Object> instance;
 
-  if (args.Length() == 0) {
-    instance = constructor->NewInstance(0, NULL);
+  v8::Local<v8::FunctionTemplate> constructorHandle =
+      NanPersistentToLocal(database_constructor);
+
+  if (location.IsEmpty()) {
+    instance = constructorHandle->GetFunction()->NewInstance(0, NULL);
   } else {
-    v8::Handle<v8::Value> argv[] = { args[0] };
-    instance = constructor->NewInstance(1, argv);
+    v8::Handle<v8::Value> argv[] = { location };
+    instance = constructorHandle->GetFunction()->NewInstance(1, argv);
   }
 
-  return scope.Close(instance);
+  return instance;
 }
 
-v8::Handle<v8::Value> Database::Open (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::Open) {
+  NanScope();
 
   LD_METHOD_SETUP_COMMON(open, 0, 1)
 
-  bool createIfMissing = BooleanOptionValueDefTrue(
+  bool createIfMissing = NanBooleanOptionValue(
       optionsObj
-    , option_createIfMissing
+    , NanSymbol("createIfMissing")
+    , true
   );
-  bool errorIfExists = BooleanOptionValue(optionsObj, option_errorIfExists);
-  bool compression = BooleanOptionValue(optionsObj, option_compression);
+  bool errorIfExists =
+      NanBooleanOptionValue(optionsObj, NanSymbol("errorIfExists"));
+  bool compression = NanBooleanOptionValue(optionsObj, NanSymbol("compression"));
 
-  uint32_t cacheSize = UInt32OptionValue(
+  uint32_t cacheSize = NanUInt32OptionValue(
       optionsObj
-    , option_cacheSize
+    , NanSymbol("cacheSize")
     , 8 << 20
   );
-  uint32_t writeBufferSize = UInt32OptionValue(
+  uint32_t writeBufferSize = NanUInt32OptionValue(
       optionsObj
-    , option_writeBufferSize
+    , NanSymbol("writeBufferSize")
     , 4 << 20
   );
-  uint32_t blockSize = UInt32OptionValue(
+  uint32_t blockSize = NanUInt32OptionValue(
       optionsObj
-    , option_blockSize
+    , NanSymbol("blockSize")
     , 4096
   );
-  uint32_t maxOpenFiles = UInt32OptionValue(
+  uint32_t maxOpenFiles = NanUInt32OptionValue(
       optionsObj
-    , option_maxOpenFiles
+    , NanSymbol("maxOpenFiles")
     , 1000
   );
-  uint32_t blockRestartInterval = UInt32OptionValue(
+  uint32_t blockRestartInterval = NanUInt32OptionValue(
       optionsObj
-    , option_blockRestartInterval
+    , NanSymbol("blockRestartInterval")
     , 16
   );
 
   OpenWorker* worker = new OpenWorker(
       database
-    , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+    , new NanCallback(callback)
     , createIfMissing
     , errorIfExists
     , compression
@@ -260,20 +232,19 @@ v8::Handle<v8::Value> Database::Open (const v8::Arguments& args) {
     , blockRestartInterval
   );
 
-  AsyncQueueWorker(worker);
+  NanAsyncQueueWorker(worker);
 
-  return v8::Undefined();
+  NanReturnUndefined();
 }
 
-v8::Handle<v8::Value> Database::Close (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::Close) {
+  NanScope();
 
   LD_METHOD_SETUP_COMMON_ONEARG(close)
 
   CloseWorker* worker = new CloseWorker(
       database
-    , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+    , new NanCallback(callback)
   );
 
   if (database->iterators.size() > 0) {
@@ -283,7 +254,7 @@ v8::Handle<v8::Value> Database::Close (const v8::Arguments& args) {
     database->pendingCloseWorker = worker;
 
     for (
-        std::map< uint32_t, v8::Persistent<v8::Object> >::iterator it
+        std::map< uint32_t, leveldown::Iterator * >::iterator it
             = database->iterators.begin()
       ; it != database->iterators.end()
       ; ++it) {
@@ -294,150 +265,132 @@ v8::Handle<v8::Value> Database::Close (const v8::Arguments& args) {
         // function and wait for it to hit ReleaseIterator() where our
         // CloseWorker will be invoked
 
+        /*
+        v8::Local<v8::Object> localHandle = NanPersistentToLocal(it->second);
         leveldown::Iterator* iterator =
-            node::ObjectWrap::Unwrap<leveldown::Iterator>(it->second);
+            node::ObjectWrap::Unwrap<leveldown::Iterator>(localHandle->
+                Get(NanSymbol("iterator")).As<v8::Object>());
+                */
+        leveldown::Iterator *iterator = it->second;
 
         if (!iterator->ended) {
           v8::Local<v8::Function> end =
-              v8::Local<v8::Function>::Cast(it->second->Get(
+              v8::Local<v8::Function>::Cast(NanObjectWrapHandle(iterator)->Get(
                   v8::String::NewSymbol("end")));
           v8::Local<v8::Value> argv[] = {
               v8::FunctionTemplate::New()->GetFunction() // empty callback
           };
           v8::TryCatch try_catch;
-          end->Call(it->second, 1, argv);
+          end->Call(NanObjectWrapHandle(iterator), 1, argv);
           if (try_catch.HasCaught()) {
             node::FatalException(try_catch);
           }
         }
     }
   } else {
-    AsyncQueueWorker(worker);
+    NanAsyncQueueWorker(worker);
   }
 
-  return v8::Undefined();
+  NanReturnUndefined();
 }
 
-v8::Handle<v8::Value> Database::Put (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::Put) {
+  NanScope();
 
   LD_METHOD_SETUP_COMMON(put, 2, 3)
 
   LD_CB_ERR_IF_NULL_OR_UNDEFINED(args[0], key)
   LD_CB_ERR_IF_NULL_OR_UNDEFINED(args[1], value)
 
-  v8::Local<v8::Value> keyBufferV = args[0];
-  v8::Local<v8::Value> valueBufferV = args[1];
-  LD_STRING_OR_BUFFER_TO_SLICE(key, keyBufferV, key)
-  LD_STRING_OR_BUFFER_TO_SLICE(value, valueBufferV, value)
-
-  v8::Persistent<v8::Value> keyBuffer =
-      v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE keyBufferV);
-  v8::Persistent<v8::Value> valueBuffer =
-      v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE valueBufferV);
+  v8::Local<v8::Object> keyHandle = args[0].As<v8::Object>();
+  v8::Local<v8::Object> valueHandle = args[1].As<v8::Object>();
+  LD_STRING_OR_BUFFER_TO_SLICE(key, keyHandle, key)
+  LD_STRING_OR_BUFFER_TO_SLICE(value, valueHandle, value)
 
-  bool sync = BooleanOptionValue(optionsObj, option_sync);
+  bool sync = NanBooleanOptionValue(optionsObj, NanSymbol("sync"));
 
   WriteWorker* worker  = new WriteWorker(
       database
-    , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+    , new NanCallback(callback)
     , key
     , value
     , sync
-    , keyBuffer
-    , valueBuffer
+    , keyHandle
+    , valueHandle
   );
-  AsyncQueueWorker(worker);
+  NanAsyncQueueWorker(worker);
 
-  return v8::Undefined();
+  NanReturnUndefined();
 }
 
-v8::Handle<v8::Value> Database::Get (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::Get) {
+  NanScope();
 
   LD_METHOD_SETUP_COMMON(get, 1, 2)
 
   LD_CB_ERR_IF_NULL_OR_UNDEFINED(args[0], key)
 
-  v8::Local<v8::Value> keyBufferV = args[0];
-  LD_STRING_OR_BUFFER_TO_SLICE(key, keyBufferV, key)
+  v8::Local<v8::Object> keyHandle = args[0].As<v8::Object>();
+  LD_STRING_OR_BUFFER_TO_SLICE(key, keyHandle, key)
 
-  v8::Persistent<v8::Value> keyBuffer = v8::Persistent<v8::Value>::New(
-      LD_NODE_ISOLATE_PRE
-      keyBufferV);
-
-  bool asBuffer = BooleanOptionValueDefTrue(optionsObj, option_asBuffer);
-  bool fillCache = BooleanOptionValueDefTrue(optionsObj, option_fillCache);
+  bool asBuffer = NanBooleanOptionValue(optionsObj, NanSymbol("asBuffer"), true);
+  bool fillCache = NanBooleanOptionValue(optionsObj, NanSymbol("fillCache"), true);
 
   ReadWorker* worker = new ReadWorker(
       database
-    , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+    , new NanCallback(callback)
     , key
     , asBuffer
     , fillCache
-    , keyBuffer
+    , keyHandle
   );
-  AsyncQueueWorker(worker);
+  NanAsyncQueueWorker(worker);
 
-  return v8::Undefined();
+  NanReturnUndefined();
 }
 
-v8::Handle<v8::Value> Database::Delete (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::Delete) {
+  NanScope();
 
   LD_METHOD_SETUP_COMMON(del, 1, 2)
 
   LD_CB_ERR_IF_NULL_OR_UNDEFINED(args[0], key)
 
-  v8::Local<v8::Value> keyBufferV = args[0];
-  LD_STRING_OR_BUFFER_TO_SLICE(key, keyBufferV, key)
-
-  v8::Persistent<v8::Value> keyBuffer =
-      v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE keyBufferV);
+  v8::Local<v8::Object> keyHandle = args[0].As<v8::Object>();
+  LD_STRING_OR_BUFFER_TO_SLICE(key, keyHandle, key)
 
-  bool sync = BooleanOptionValue(optionsObj, option_sync);
+  bool sync = NanBooleanOptionValue(optionsObj, NanSymbol("sync"));
 
   DeleteWorker* worker = new DeleteWorker(
       database
-    , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+    , new NanCallback(callback)
     , key
     , sync
-    , keyBuffer
+    , keyHandle
   );
-  AsyncQueueWorker(worker);
+  NanAsyncQueueWorker(worker);
 
-  return v8::Undefined();
+  NanReturnUndefined();
 }
 
-/* property key & value strings for elements of the array sent to batch() */
-LD_SYMBOL ( str_key   , key   );
-LD_SYMBOL ( str_value , value );
-LD_SYMBOL ( str_type  , type  );
-LD_SYMBOL ( str_del   , del   );
-LD_SYMBOL ( str_put   , put   );
-
-v8::Handle<v8::Value> Database::Batch (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::Batch) {
+  NanScope();
 
   if ((args.Length() == 0 || args.Length() == 1) && !args[0]->IsArray()) {
     v8::Local<v8::Object> optionsObj;
     if (args.Length() > 0 && args[0]->IsObject()) {
-      optionsObj = v8::Local<v8::Object>::Cast(args[0]);
+      optionsObj = args[0].As<v8::Object>();
     }
-    return scope.Close(Batch::NewInstance(args.This(), optionsObj));
+    NanReturnValue(Batch::NewInstance(args.This(), optionsObj));
   }
 
   LD_METHOD_SETUP_COMMON(batch, 1, 2)
 
-  bool sync = BooleanOptionValue(optionsObj, option_sync);
+  bool sync = NanBooleanOptionValue(optionsObj, NanSymbol("sync"));
 
   v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[0]);
 
-  std::vector< Reference >* references = new std::vector< Reference >;
+  std::vector< Reference *>* references = new std::vector< Reference *>;
   leveldb::WriteBatch* batch = new leveldb::WriteBatch();
   bool hasData = false;
 
@@ -447,24 +400,21 @@ v8::Handle<v8::Value> Database::Batch (const v8::Arguments& args) {
 
     v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(array->Get(i));
 
-    LD_CB_ERR_IF_NULL_OR_UNDEFINED(obj->Get(str_type), type)
+    LD_CB_ERR_IF_NULL_OR_UNDEFINED(obj->Get(NanSymbol("type")), type)
 
-    v8::Local<v8::Value> keyBuffer = obj->Get(str_key);
+    v8::Local<v8::Value> keyBuffer = obj->Get(NanSymbol("key"));
     LD_CB_ERR_IF_NULL_OR_UNDEFINED(keyBuffer, key)
 
-    if (obj->Get(str_type)->StrictEquals(str_del)) {
+    if (obj->Get(NanSymbol("type"))->StrictEquals(NanSymbol("del"))) {
       LD_STRING_OR_BUFFER_TO_SLICE(key, keyBuffer, key)
 
       batch->Delete(key);
       if (!hasData)
         hasData = true;
 
-      references->push_back(Reference(
-          v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE keyBuffer)
-        , key
-      ));
-    } else if (obj->Get(str_type)->StrictEquals(str_put)) {
-      v8::Local<v8::Value> valueBuffer = obj->Get(str_value);
+      references->push_back(new Reference(keyBuffer, key));
+    } else if (obj->Get(NanSymbol("type"))->StrictEquals(NanSymbol("put"))) {
+      v8::Local<v8::Value> valueBuffer = obj->Get(NanSymbol("value"));
       LD_CB_ERR_IF_NULL_OR_UNDEFINED(valueBuffer, value)
 
       LD_STRING_OR_BUFFER_TO_SLICE(key, keyBuffer, key)
@@ -474,22 +424,16 @@ v8::Handle<v8::Value> Database::Batch (const v8::Arguments& args) {
       if (!hasData)
         hasData = true;
 
-      references->push_back(Reference(
-          v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE keyBuffer)
-        , key
-      ));
-      references->push_back(Reference(
-          v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE valueBuffer)
-        , value
-      ));
+      references->push_back(new Reference(keyBuffer, key));
+      references->push_back(new Reference(valueBuffer, value));
     }
   }
 
   // don't allow an empty batch through
   if (hasData) {
-    AsyncQueueWorker(new BatchWorker(
+    NanAsyncQueueWorker(new BatchWorker(
         database
-      , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+      , new NanCallback(callback)
       , batch
       , references
       , sync
@@ -499,24 +443,23 @@ v8::Handle<v8::Value> Database::Batch (const v8::Arguments& args) {
     LD_RUN_CALLBACK(callback, NULL, 0);
   }
 
-  return v8::Undefined();
+  NanReturnUndefined();
 }
 
-v8::Handle<v8::Value> Database::ApproximateSize (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::ApproximateSize) {
+  NanScope();
 
-  v8::Local<v8::Value> startBufferV = args[0];
-  v8::Local<v8::Value> endBufferV = args[1];
+  v8::Local<v8::Object> startHandle = args[0].As<v8::Object>();
+  v8::Local<v8::Object> endHandle = args[1].As<v8::Object>();
 
-  if (startBufferV->IsNull()
-      || startBufferV->IsUndefined()
-      || startBufferV->IsFunction() // callback in pos 0?
-      || endBufferV->IsNull()
-      || endBufferV->IsUndefined()
-      || endBufferV->IsFunction() // callback in pos 1?
+  if (startHandle->IsNull()
+      || startHandle->IsUndefined()
+      || startHandle->IsFunction() // callback in pos 0?
+      || endHandle->IsNull()
+      || endHandle->IsUndefined()
+      || endHandle->IsFunction() // callback in pos 1?
       ) {
-    LD_THROW_RETURN(approximateSize() requires valid `start`, `end` and `callback` arguments)
+    return NanThrowError("approximateSize() requires valid `start`, `end` and `callback` arguments");
   }
 
   LD_METHOD_SETUP_COMMON(approximateSize, -1, 2)
@@ -524,41 +467,34 @@ v8::Handle<v8::Value> Database::ApproximateSize (const v8::Arguments& args) {
   LD_CB_ERR_IF_NULL_OR_UNDEFINED(args[0], start)
   LD_CB_ERR_IF_NULL_OR_UNDEFINED(args[1], end)
 
-  LD_STRING_OR_BUFFER_TO_SLICE(start, startBufferV, start)
-  LD_STRING_OR_BUFFER_TO_SLICE(end, endBufferV, end)
-
-  v8::Persistent<v8::Value> startBuffer =
-      v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE startBufferV);
-  v8::Persistent<v8::Value> endBuffer =
-      v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE endBufferV);
+  LD_STRING_OR_BUFFER_TO_SLICE(start, startHandle, start)
+  LD_STRING_OR_BUFFER_TO_SLICE(end, endHandle, end)
 
   ApproximateSizeWorker* worker  = new ApproximateSizeWorker(
       database
-    , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+    , new NanCallback(callback)
     , start
     , end
-    , startBuffer
-    , endBuffer
+    , startHandle
+    , endHandle
   );
-  AsyncQueueWorker(worker);
+  NanAsyncQueueWorker(worker);
 
-  return v8::Undefined();
+  NanReturnUndefined();
 }
 
-v8::Handle<v8::Value> Database::GetProperty (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::GetProperty) {
+  NanScope();
 
-  v8::Local<v8::Value> propertyV = args[0];
+  v8::Local<v8::Value> propertyHandle = args[0].As<v8::Object>();
   v8::Local<v8::Function> callback; // for LD_CB_ERR_IF_NULL_OR_UNDEFINED
 
-  if (!propertyV->IsString()) {
-    LD_THROW_RETURN(getProperty() requires a valid `property` argument)
-  }
+  if (!propertyHandle->IsString())
+    return NanThrowError("getProperty() requires a valid `property` argument");
 
-  LD_CB_ERR_IF_NULL_OR_UNDEFINED(propertyV, property)
+  LD_CB_ERR_IF_NULL_OR_UNDEFINED(propertyHandle, property)
 
-  LD_STRING_OR_BUFFER_TO_SLICE(property, propertyV, property)
+  LD_STRING_OR_BUFFER_TO_SLICE(property, propertyHandle, property)
 
   leveldown::Database* database =
       node::ObjectWrap::Unwrap<leveldown::Database>(args.This());
@@ -570,12 +506,11 @@ v8::Handle<v8::Value> Database::GetProperty (const v8::Arguments& args) {
   delete value;
   delete[] property.data();
 
-  return returnValue;
+  NanReturnValue(returnValue);
 }
 
-v8::Handle<v8::Value> Database::Iterator (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Database::Iterator) {
+  NanScope();
 
   Database* database = node::ObjectWrap::Unwrap<Database>(args.This());
 
@@ -588,7 +523,7 @@ v8::Handle<v8::Value> Database::Iterator (const v8::Arguments& args) {
   // easily store & lookup on our `iterators` map
   uint32_t id = database->currentIteratorId++;
   v8::TryCatch try_catch;
-  v8::Handle<v8::Object> iterator = Iterator::NewInstance(
+  v8::Local<v8::Object> iteratorHandle = Iterator::NewInstance(
       args.This()
     , v8::Number::New(id)
     , optionsObj
@@ -597,12 +532,22 @@ v8::Handle<v8::Value> Database::Iterator (const v8::Arguments& args) {
     node::FatalException(try_catch);
   }
 
-  // register our iterator
-  database->iterators[id] =
-      v8::Persistent<v8::Object>::New(LD_NODE_ISOLATE_PRE
-          node::ObjectWrap::Unwrap<leveldown::Iterator>(iterator)->handle_);
+  leveldown::Iterator *iterator =
+      node::ObjectWrap::Unwrap<leveldown::Iterator>(iteratorHandle);
 
-  return scope.Close(iterator);
+  database->iterators[id] = iterator;
+
+  // register our iterator
+  /*
+  v8::Local<v8::Object> obj = v8::Object::New();
+  obj->Set(NanSymbol("iterator"), iteratorHandle);
+  v8::Persistent<v8::Object> persistent;
+  persistent.Reset(nan_isolate, obj);
+  database->iterators.insert(std::pair< uint32_t, v8::Persistent<v8::Object> & >
+      (id, persistent));
+  */
+
+  NanReturnValue(iteratorHandle);
 }
 
 
diff --git a/src/database.h b/src/database.h
index 821edb1..2310f83 100644
--- a/src/database.h
+++ b/src/database.h
@@ -11,38 +11,30 @@
 #include <node.h>
 
 #include "leveldb/db.h"
-
+#include "nan.h"
 #include "leveldown.h"
+#include "iterator.h"
 
 namespace leveldown {
 
-LD_SYMBOL ( option_createIfMissing , createIfMissing ); // for open()
-LD_SYMBOL ( option_errorIfExists   , errorIfExists   ); // for open()
-LD_SYMBOL ( option_compression     , compression     ); // for open()
-LD_SYMBOL ( option_cacheSize       , cacheSize       ); // for open() 
-LD_SYMBOL ( option_writeBufferSize , writeBufferSize ); // for open() 
-LD_SYMBOL ( option_blockSize       , blockSize       ); // for open() 
-LD_SYMBOL ( option_maxOpenFiles    , maxOpenFiles    ); // for open() 
-LD_SYMBOL ( option_blockRestartInterval , blockRestartInterval ); // for open() 
-LD_SYMBOL ( option_sync            , sync            ); // for put() and delete()
-LD_SYMBOL ( option_asBuffer        , asBuffer        ); // for get()
-LD_SYMBOL ( option_fillCache       , fillcache       ); // for get() and readStream()
-
-v8::Handle<v8::Value> LevelDOWN (const v8::Arguments& args);
+NAN_METHOD(LevelDOWN);
 
 struct Reference {
-  v8::Persistent<v8::Value> ptr;
+  v8::Persistent<v8::Object> handle;
   leveldb::Slice slice;
-  Reference(v8::Persistent<v8::Value> ptr, leveldb::Slice slice) :
-      ptr(ptr)
-    , slice(slice) { };
+
+  Reference(v8::Local<v8::Value> obj, leveldb::Slice slice) : slice(slice) {
+    v8::Local<v8::Object> _obj = v8::Object::New();
+    _obj->Set(NanSymbol("obj"), obj);
+    NanAssignPersistent(v8::Object, handle, _obj);
+  };
 };
 
-static inline void ClearReferences (std::vector<Reference>* references) {
-  for (std::vector<Reference>::iterator it = references->begin()
+static inline void ClearReferences (std::vector<Reference *> *references) {
+  for (std::vector<Reference *>::iterator it = references->begin()
       ; it != references->end()
       ; ) {
-    DisposeStringOrBufferFromSlice(it->ptr, it->slice);
+    DisposeStringOrBufferFromSlice((*it)->handle, (*it)->slice);
     it = references->erase(it);
   }
   delete references;
@@ -51,7 +43,7 @@ static inline void ClearReferences (std::vector<Reference>* references) {
 class Database : public node::ObjectWrap {
 public:
   static void Init ();
-  static v8::Handle<v8::Value> NewInstance (const v8::Arguments& args);
+  static v8::Handle<v8::Value> NewInstance (v8::Local<v8::String> &location);
 
   leveldb::Status OpenDatabase (leveldb::Options* options, std::string location);
   leveldb::Status PutToDatabase (
@@ -90,23 +82,22 @@ private:
   uint32_t currentIteratorId;
   void(*pendingCloseWorker);
 
-  std::map< uint32_t, v8::Persistent<v8::Object> > iterators;
+  std::map< uint32_t, leveldown::Iterator * > iterators;
 
-  static v8::Persistent<v8::Function> constructor;
   static void WriteDoing(uv_work_t *req);
   static void WriteAfter(uv_work_t *req);
 
-  LD_V8_METHOD( New      )
-  LD_V8_METHOD( Open     )
-  LD_V8_METHOD( Close    )
-  LD_V8_METHOD( Put      )
-  LD_V8_METHOD( Delete   )
-  LD_V8_METHOD( Get      )
-  LD_V8_METHOD( Batch    )
-  LD_V8_METHOD( Write    )
-  LD_V8_METHOD( Iterator )
-  LD_V8_METHOD( ApproximateSize )
-  LD_V8_METHOD( GetProperty )
+  static NAN_METHOD(New);
+  static NAN_METHOD(Open);
+  static NAN_METHOD(Close);
+  static NAN_METHOD(Put);
+  static NAN_METHOD(Delete);
+  static NAN_METHOD(Get);
+  static NAN_METHOD(Batch);
+  static NAN_METHOD(Write);
+  static NAN_METHOD(Iterator);
+  static NAN_METHOD(ApproximateSize);
+  static NAN_METHOD(GetProperty);
 };
 
 } // namespace leveldown
diff --git a/src/database_async.cc b/src/database_async.cc
index bc11424..9f4c47d 100644
--- a/src/database_async.cc
+++ b/src/database_async.cc
@@ -16,8 +16,8 @@ namespace leveldown {
 /** OPEN WORKER **/
 
 OpenWorker::OpenWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
+    Database *database
+  , NanCallback *callback
   , bool createIfMissing
   , bool errorIfExists
   , bool compression
@@ -46,14 +46,14 @@ OpenWorker::~OpenWorker () {
 }
 
 void OpenWorker::Execute () {
-  status = database->OpenDatabase(options, database->Location());
+  SetStatus(database->OpenDatabase(options, database->Location()));
 }
 
 /** CLOSE WORKER **/
 
 CloseWorker::CloseWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
+    Database *database
+  , NanCallback *callback
 ) : AsyncWorker(database, callback)
 {};
 
@@ -64,46 +64,46 @@ void CloseWorker::Execute () {
 }
 
 void CloseWorker::WorkComplete () {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+  NanScope();
 
   HandleOKCallback();
-  callback.Dispose(LD_NODE_ISOLATE);
 }
 
 /** IO WORKER (abstract) **/
 
 IOWorker::IOWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
+    Database *database
+  , NanCallback *callback
   , leveldb::Slice key
-  , v8::Persistent<v8::Value> keyPtr
+  , v8::Local<v8::Object> &keyHandle
 ) : AsyncWorker(database, callback)
   , key(key)
-  , keyPtr(keyPtr)
-{};
+{
+  SavePersistent("key", keyHandle);
+};
 
 IOWorker::~IOWorker () {}
 
 void IOWorker::WorkComplete () {
-  DisposeStringOrBufferFromSlice(keyPtr, key);
+  DisposeStringOrBufferFromSlice(GetFromPersistent("key"), key);
   AsyncWorker::WorkComplete();
 }
 
 /** READ WORKER **/
 
 ReadWorker::ReadWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
+    Database *database
+  , NanCallback *callback
   , leveldb::Slice key
   , bool asBuffer
   , bool fillCache
-  , v8::Persistent<v8::Value> keyPtr
-) : IOWorker(database, callback, key, keyPtr)
+  , v8::Local<v8::Object> &keyHandle
+) : IOWorker(database, callback, key, keyHandle)
   , asBuffer(asBuffer)
 {
   options = new leveldb::ReadOptions();
   options->fill_cache = fillCache;
+  SavePersistent("key", keyHandle);
 };
 
 ReadWorker::~ReadWorker () {
@@ -111,16 +111,15 @@ ReadWorker::~ReadWorker () {
 }
 
 void ReadWorker::Execute () {
-  status = database->GetFromDatabase(options, key, value);
+  SetStatus(database->GetFromDatabase(options, key, value));
 }
 
 void ReadWorker::HandleOKCallback () {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+  NanScope();
 
   v8::Local<v8::Value> returnValue;
   if (asBuffer) {
-    returnValue = LD_NEW_BUFFER_HANDLE((char*)value.data(), value.size());
+    returnValue = NanNewBufferHandle((char*)value.data(), value.size());
   } else {
     returnValue = v8::String::New((char*)value.data(), value.size());
   }
@@ -128,21 +127,22 @@ void ReadWorker::HandleOKCallback () {
       v8::Local<v8::Value>::New(v8::Null())
     , returnValue
   };
-  LD_RUN_CALLBACK(callback, argv, 2);
+  callback->Run(2, argv);
 }
 
 /** DELETE WORKER **/
 
 DeleteWorker::DeleteWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
+    Database *database
+  , NanCallback *callback
   , leveldb::Slice key
   , bool sync
-  , v8::Persistent<v8::Value> keyPtr
-) : IOWorker(database, callback, key, keyPtr)
+  , v8::Local<v8::Object> &keyHandle
+) : IOWorker(database, callback, key, keyHandle)
 {
   options = new leveldb::WriteOptions();
   options->sync = sync;
+  SavePersistent("key", keyHandle);
 };
 
 DeleteWorker::~DeleteWorker () {
@@ -150,42 +150,43 @@ DeleteWorker::~DeleteWorker () {
 }
 
 void DeleteWorker::Execute () {
-  status = database->DeleteFromDatabase(options, key);
+  SetStatus(database->DeleteFromDatabase(options, key));
 }
 
 /** WRITE WORKER **/
 
 WriteWorker::WriteWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
+    Database *database
+  , NanCallback *callback
   , leveldb::Slice key
   , leveldb::Slice value
   , bool sync
-  , v8::Persistent<v8::Value> keyPtr
-  , v8::Persistent<v8::Value> valuePtr
-) : DeleteWorker(database, callback, key, sync, keyPtr)
+  , v8::Local<v8::Object> &keyHandle
+  , v8::Local<v8::Object> &valueHandle
+) : DeleteWorker(database, callback, key, sync, keyHandle)
   , value(value)
-  , valuePtr(valuePtr)
-{};
+{
+  SavePersistent("value", valueHandle);
+};
 
 WriteWorker::~WriteWorker () {}
 
 void WriteWorker::Execute () {
-  status = database->PutToDatabase(options, key, value);
+  SetStatus(database->PutToDatabase(options, key, value));
 }
 
 void WriteWorker::WorkComplete () {
-  DisposeStringOrBufferFromSlice(valuePtr, value);
+  DisposeStringOrBufferFromSlice(GetFromPersistent("value"), value);
   IOWorker::WorkComplete();
 }
 
 /** BATCH WORKER **/
 
 BatchWorker::BatchWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
+    Database *database
+  , NanCallback *callback
   , leveldb::WriteBatch* batch
-  , std::vector<Reference>* references
+  , std::vector<Reference *>* references
   , bool sync
 ) : AsyncWorker(database, callback)
   , batch(batch)
@@ -201,23 +202,24 @@ BatchWorker::~BatchWorker () {
 }
 
 void BatchWorker::Execute () {
-  status = database->WriteBatchToDatabase(options, batch);
+  SetStatus(database->WriteBatchToDatabase(options, batch));
 }
 
 /** APPROXIMATE SIZE WORKER **/
 
 ApproximateSizeWorker::ApproximateSizeWorker (
-    Database* database
-  , v8::Persistent<v8::Function> callback
+    Database *database
+  , NanCallback *callback
   , leveldb::Slice start
   , leveldb::Slice end
-  , v8::Persistent<v8::Value> startPtr
-  , v8::Persistent<v8::Value> endPtr
+  , v8::Local<v8::Object> &startHandle
+  , v8::Local<v8::Object> &endHandle
 ) : AsyncWorker(database, callback)
   , range(start, end)
-  , startPtr(startPtr)
-  , endPtr(endPtr)
-{};
+{
+  SavePersistent("start", startHandle);
+  SavePersistent("end", endHandle);
+};
 
 ApproximateSizeWorker::~ApproximateSizeWorker () {}
 
@@ -226,21 +228,20 @@ void ApproximateSizeWorker::Execute () {
 }
 
 void ApproximateSizeWorker::WorkComplete() {
-  DisposeStringOrBufferFromSlice(startPtr, range.start);
-  DisposeStringOrBufferFromSlice(endPtr, range.limit);
+  DisposeStringOrBufferFromSlice(GetFromPersistent("start"), range.start);
+  DisposeStringOrBufferFromSlice(GetFromPersistent("end"), range.limit);
   AsyncWorker::WorkComplete();
 }
 
 void ApproximateSizeWorker::HandleOKCallback () {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+  NanScope();
 
   v8::Local<v8::Value> returnValue = v8::Number::New((double) size);
   v8::Local<v8::Value> argv[] = {
       v8::Local<v8::Value>::New(v8::Null())
     , returnValue
   };
-  LD_RUN_CALLBACK(callback, argv, 2);
+  callback->Run(2, argv);
 }
 
 } // namespace leveldown
diff --git a/src/database_async.h b/src/database_async.h
index 80dafff..909e7e6 100644
--- a/src/database_async.h
+++ b/src/database_async.h
@@ -18,8 +18,8 @@ namespace leveldown {
 class OpenWorker : public AsyncWorker {
 public:
   OpenWorker (
-      Database* database
-    , v8::Persistent<v8::Function> callback
+      Database *database
+    , NanCallback *callback
     , bool createIfMissing
     , bool errorIfExists
     , bool compression
@@ -40,8 +40,8 @@ private:
 class CloseWorker : public AsyncWorker {
 public:
   CloseWorker (
-      Database* database
-    , v8::Persistent<v8::Function> callback
+      Database *database
+    , NanCallback *callback
   );
 
   virtual ~CloseWorker ();
@@ -52,10 +52,10 @@ public:
 class IOWorker    : public AsyncWorker {
 public:
   IOWorker (
-      Database* database
-    , v8::Persistent<v8::Function> callback
+      Database *database
+    , NanCallback *callback
     , leveldb::Slice key
-    , v8::Persistent<v8::Value> keyPtr
+    , v8::Local<v8::Object> &keyHandle
   );
 
   virtual ~IOWorker ();
@@ -63,18 +63,17 @@ public:
 
 protected:
   leveldb::Slice key;
-  v8::Persistent<v8::Value> keyPtr;
 };
 
 class ReadWorker : public IOWorker {
 public:
   ReadWorker (
-      Database* database
-    , v8::Persistent<v8::Function> callback
+      Database *database
+    , NanCallback *callback
     , leveldb::Slice key
     , bool asBuffer
     , bool fillCache
-    , v8::Persistent<v8::Value> keyPtr
+    , v8::Local<v8::Object> &keyHandle
   );
 
   virtual ~ReadWorker ();
@@ -90,11 +89,11 @@ private:
 class DeleteWorker : public IOWorker {
 public:
   DeleteWorker (
-      Database* database
-    , v8::Persistent<v8::Function> callback
+      Database *database
+    , NanCallback *callback
     , leveldb::Slice key
     , bool sync
-    , v8::Persistent<v8::Value> keyPtr
+    , v8::Local<v8::Object> &keyHandle
   );
 
   virtual ~DeleteWorker ();
@@ -107,13 +106,13 @@ protected:
 class WriteWorker : public DeleteWorker {
 public:
   WriteWorker (
-      Database* database
-    , v8::Persistent<v8::Function> callback
+      Database *database
+    , NanCallback *callback
     , leveldb::Slice key
     , leveldb::Slice value
     , bool sync
-    , v8::Persistent<v8::Value> keyPtr
-    , v8::Persistent<v8::Value> valuePtr
+    , v8::Local<v8::Object> &keyHandle
+    , v8::Local<v8::Object> &valueHandle
   );
 
   virtual ~WriteWorker ();
@@ -122,16 +121,15 @@ public:
 
 private:
   leveldb::Slice value;
-  v8::Persistent<v8::Value> valuePtr;
 };
 
 class BatchWorker : public AsyncWorker {
 public:
   BatchWorker (
-      Database* database
-    , v8::Persistent<v8::Function> callback
+      Database *database
+    , NanCallback *callback
     , leveldb::WriteBatch* batch
-    , std::vector<Reference>* references
+    , std::vector<Reference *>* references
     , bool sync
   );
 
@@ -141,18 +139,18 @@ public:
 private:
   leveldb::WriteOptions* options;
   leveldb::WriteBatch* batch;
-  std::vector<Reference>* references;
+  std::vector<Reference *>* references;
 };
 
 class ApproximateSizeWorker : public AsyncWorker {
 public:
   ApproximateSizeWorker (
-      Database* database
-    , v8::Persistent<v8::Function> callback
+      Database *database
+    , NanCallback *callback
     , leveldb::Slice start
     , leveldb::Slice end
-    , v8::Persistent<v8::Value> startPtr
-    , v8::Persistent<v8::Value> endPtr
+    , v8::Local<v8::Object> &startHandle
+    , v8::Local<v8::Object> &endHandle
   );
 
   virtual ~ApproximateSizeWorker ();
@@ -162,8 +160,6 @@ public:
 
   private:
     leveldb::Range range;
-    v8::Persistent<v8::Value> startPtr;
-    v8::Persistent<v8::Value> endPtr;
     uint64_t size;
 };
 
diff --git a/src/iterator.cc b/src/iterator.cc
index 52a2493..d6b4553 100644
--- a/src/iterator.cc
+++ b/src/iterator.cc
@@ -12,6 +12,8 @@
 
 namespace leveldown {
 
+static v8::Persistent<v8::FunctionTemplate> iterator_constructor;
+
 Iterator::Iterator (
     Database* database
   , uint32_t id
@@ -24,7 +26,7 @@ Iterator::Iterator (
   , bool fillCache
   , bool keyAsBuffer
   , bool valueAsBuffer
-  , v8::Persistent<v8::Value> startPtr
+  , v8::Local<v8::Object> &startHandle
 ) : database(database)
   , id(id)
   , start(start)
@@ -35,8 +37,14 @@ Iterator::Iterator (
   , limit(limit)
   , keyAsBuffer(keyAsBuffer)
   , valueAsBuffer(valueAsBuffer)
-  , startPtr(startPtr)
 {
+  NanScope();
+
+  v8::Local<v8::Object> obj = v8::Object::New();
+  if (!startHandle.IsEmpty())
+    obj->Set(NanSymbol("start"), startHandle);
+  NanAssignPersistent(v8::Object, persistentHandle, obj)
+
   options    = new leveldb::ReadOptions();
   options->fill_cache = fillCache;
   dbIterator = NULL;
@@ -48,9 +56,9 @@ Iterator::Iterator (
 
 
 Iterator::~Iterator () {
-  LD_NODE_ISOLATE_DECL
   delete options;
-  startPtr.Dispose(LD_NODE_ISOLATE);
+  if (!persistentHandle.IsEmpty())
+    NanDispose(persistentHandle);
   if (start != NULL)
     delete start;
   if (end != NULL)
@@ -121,23 +129,21 @@ void Iterator::Release () {
 void checkEndCallback (Iterator* iterator) {
   iterator->nexting = false;
   if (iterator->endWorker != NULL) {
-    AsyncQueueWorker(iterator->endWorker);
+    NanAsyncQueueWorker(iterator->endWorker);
     iterator->endWorker = NULL;
   }
 }
 
 //void *ctx, void (*callback)(void *ctx, leveldb::Slice key, leveldb::Slice value)
-v8::Handle<v8::Value> Iterator::Next (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Iterator::Next) {
+  NanScope();
 
   Iterator* iterator = node::ObjectWrap::Unwrap<Iterator>(args.This());
 
-  if (args.Length() == 0 || !args[0]->IsFunction()) {
-    LD_THROW_RETURN(next() requires a callback argument)
-  }
+  if (args.Length() == 0 || !args[0]->IsFunction())
+    return NanThrowError("next() requires a callback argument");
 
-  v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[0]);
+  v8::Local<v8::Function> callback = args[0].As<v8::Function>();
 
   if (iterator->ended) {
     LD_RETURN_CALLBACK_OR_ERROR(callback, "cannot call next() after end()")
@@ -149,24 +155,22 @@ v8::Handle<v8::Value> Iterator::Next (const v8::Arguments& args) {
 
   NextWorker* worker = new NextWorker(
       iterator
-    , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+    , new NanCallback(callback)
     , checkEndCallback
   );
   iterator->nexting = true;
-  AsyncQueueWorker(worker);
+  NanAsyncQueueWorker(worker);
 
-  return scope.Close(args.Holder());
+  NanReturnValue(args.Holder());
 }
 
-v8::Handle<v8::Value> Iterator::End (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Iterator::End) {
+  NanScope();
 
   Iterator* iterator = node::ObjectWrap::Unwrap<Iterator>(args.This());
 
-  if (args.Length() == 0 || !args[0]->IsFunction()) {
-    LD_THROW_RETURN(end() requires a callback argument)
-  }
+  if (args.Length() == 0 || !args[0]->IsFunction())
+    return NanThrowError("end() requires a callback argument");
 
   v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[0]);
 
@@ -176,7 +180,7 @@ v8::Handle<v8::Value> Iterator::End (const v8::Arguments& args) {
 
   EndWorker* worker = new EndWorker(
       iterator
-    , v8::Persistent<v8::Function>::New(LD_NODE_ISOLATE_PRE callback)
+    , new NanCallback(callback)
   );
   iterator->ended = true;
 
@@ -184,64 +188,54 @@ v8::Handle<v8::Value> Iterator::End (const v8::Arguments& args) {
     // waiting for a next() to return, queue the end
     iterator->endWorker = worker;
   } else {
-    AsyncQueueWorker(worker);
+    NanAsyncQueueWorker(worker);
   }
 
-  return scope.Close(args.Holder());
+  NanReturnValue(args.Holder());
 }
 
-v8::Persistent<v8::Function> Iterator::constructor;
-
 void Iterator::Init () {
-  LD_NODE_ISOLATE_DECL
-  v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(New);
-  tpl->SetClassName(v8::String::NewSymbol("Iterator"));
+  v8::Local<v8::FunctionTemplate> tpl =
+      v8::FunctionTemplate::New(Iterator::New);
+  NanAssignPersistent(v8::FunctionTemplate, iterator_constructor, tpl)
+  tpl->SetClassName(NanSymbol("Iterator"));
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("next")
-    , v8::FunctionTemplate::New(Next)->GetFunction()
-  );
-  tpl->PrototypeTemplate()->Set(
-      v8::String::NewSymbol("end")
-    , v8::FunctionTemplate::New(End)->GetFunction()
-  );
-  constructor = v8::Persistent<v8::Function>::New(
-      LD_NODE_ISOLATE_PRE
-      tpl->GetFunction());
+  NODE_SET_PROTOTYPE_METHOD(tpl, "next", Iterator::Next);
+  NODE_SET_PROTOTYPE_METHOD(tpl, "end", Iterator::End);
 }
 
-v8::Handle<v8::Object> Iterator::NewInstance (
-        v8::Handle<v8::Object> database
-      , v8::Handle<v8::Number> id
-      , v8::Handle<v8::Object> optionsObj
+v8::Local<v8::Object> Iterator::NewInstance (
+        v8::Local<v8::Object> database
+      , v8::Local<v8::Number> id
+      , v8::Local<v8::Object> optionsObj
     ) {
 
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+  NanScope();
 
   v8::Local<v8::Object> instance;
+  v8::Local<v8::FunctionTemplate> constructorHandle =
+      NanPersistentToLocal(iterator_constructor);
 
   if (optionsObj.IsEmpty()) {
     v8::Handle<v8::Value> argv[2] = { database, id };
-    instance = constructor->NewInstance(2, argv);
+    instance = constructorHandle->GetFunction()->NewInstance(2, argv);
   } else {
     v8::Handle<v8::Value> argv[3] = { database, id, optionsObj };
-    instance = constructor->NewInstance(3, argv);
+    instance = constructorHandle->GetFunction()->NewInstance(3, argv);
   }
 
-  return scope.Close(instance);
+  return instance;
 }
 
-v8::Handle<v8::Value> Iterator::New (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(Iterator::New) {
+  NanScope();
 
   Database* database = node::ObjectWrap::Unwrap<Database>(args[0]->ToObject());
 
   //TODO: remove this, it's only here to make LD_STRING_OR_BUFFER_TO_SLICE happy
   v8::Handle<v8::Function> callback;
 
-  v8::Local<v8::Value> startBuffer;
+  v8::Local<v8::Object> startHandle;
   leveldb::Slice* start = NULL;
   std::string* end = NULL;
   int limit = -1;
@@ -253,25 +247,25 @@ v8::Handle<v8::Value> Iterator::New (const v8::Arguments& args) {
   if (args.Length() > 1 && args[2]->IsObject()) {
     optionsObj = v8::Local<v8::Object>::Cast(args[2]);
 
-    if (optionsObj->Has(option_start)
-        && (node::Buffer::HasInstance(optionsObj->Get(option_start))
-          || optionsObj->Get(option_start)->IsString())) {
+    if (optionsObj->Has(NanSymbol("start"))
+        && (node::Buffer::HasInstance(optionsObj->Get(NanSymbol("start")))
+          || optionsObj->Get(NanSymbol("start"))->IsString())) {
 
-      startBuffer = v8::Local<v8::Value>::New(optionsObj->Get(option_start));
+      startHandle = optionsObj->Get(NanSymbol("start")).As<v8::Object>();
 
       // ignore start if it has size 0 since a Slice can't have length 0
-      if (StringOrBufferLength(startBuffer) > 0) {
-        LD_STRING_OR_BUFFER_TO_SLICE(_start, startBuffer, start)
+      if (StringOrBufferLength(startHandle) > 0) {
+        LD_STRING_OR_BUFFER_TO_SLICE(_start, startHandle, start)
         start = new leveldb::Slice(_start.data(), _start.size());
       }
     }
 
-    if (optionsObj->Has(option_end)
-        && (node::Buffer::HasInstance(optionsObj->Get(option_end))
-          || optionsObj->Get(option_end)->IsString())) {
+    if (optionsObj->Has(NanSymbol("end"))
+        && (node::Buffer::HasInstance(optionsObj->Get(NanSymbol("end")))
+          || optionsObj->Get(NanSymbol("end"))->IsString())) {
 
       v8::Local<v8::Value> endBuffer =
-          v8::Local<v8::Value>::New(optionsObj->Get(option_end));
+          v8::Local<v8::Value>::New(optionsObj->Get(NanSymbol("end")));
 
       // ignore end if it has size 0 since a Slice can't have length 0
       if (StringOrBufferLength(endBuffer) > 0) {
@@ -280,21 +274,26 @@ v8::Handle<v8::Value> Iterator::New (const v8::Arguments& args) {
       }
     }
 
-    if (!optionsObj.IsEmpty() && optionsObj->Has(option_limit)) {
-      limit =
-        v8::Local<v8::Integer>::Cast(optionsObj->Get(option_limit))->Value();
+    if (!optionsObj.IsEmpty() && optionsObj->Has(NanSymbol("limit"))) {
+      limit = v8::Local<v8::Integer>::Cast(optionsObj->Get(
+          NanSymbol("limit")))->Value();
     }
   }
 
-  bool reverse      = BooleanOptionValue(optionsObj, option_reverse);
-  bool keys         = BooleanOptionValueDefTrue(optionsObj, option_keys);
-  bool values       = BooleanOptionValueDefTrue(optionsObj, option_values);
-  bool keyAsBuffer  = BooleanOptionValueDefTrue(optionsObj, option_keyAsBuffer);
-  bool valueAsBuffer = BooleanOptionValueDefTrue(
+  bool reverse = NanBooleanOptionValue(optionsObj, NanSymbol("reverse"));
+  bool keys = NanBooleanOptionValue(optionsObj, NanSymbol("keys"), true);
+  bool values = NanBooleanOptionValue(optionsObj, NanSymbol("values"), true);
+  bool keyAsBuffer = NanBooleanOptionValue(
+      optionsObj
+    , NanSymbol("keyAsBuffer")
+    , true
+  );
+  bool valueAsBuffer = NanBooleanOptionValue(
       optionsObj
-    , option_valueAsBuffer
+    , NanSymbol("valueAsBuffer")
+    , true
   );
-  bool fillCache    = BooleanOptionValue(optionsObj, option_fillCache);
+  bool fillCache = NanBooleanOptionValue(optionsObj, NanSymbol("fillCache"));
 
   Iterator* iterator = new Iterator(
       database
@@ -308,11 +307,11 @@ v8::Handle<v8::Value> Iterator::New (const v8::Arguments& args) {
     , fillCache
     , keyAsBuffer
     , valueAsBuffer
-    , v8::Persistent<v8::Value>::New(LD_NODE_ISOLATE_PRE startBuffer)
+    , startHandle
   );
   iterator->Wrap(args.This());
 
-  return args.This();
+  NanReturnValue(args.This());
 }
 
 } // namespace leveldown
diff --git a/src/iterator.h b/src/iterator.h
index fe9545c..4893dea 100644
--- a/src/iterator.h
+++ b/src/iterator.h
@@ -8,30 +8,25 @@
 
 #include <node.h>
 
+#include "nan.h"
 #include "leveldown.h"
 #include "database.h"
 #include "async.h"
 
 namespace leveldown {
 
-LD_SYMBOL ( option_start         , start         );
-LD_SYMBOL ( option_end           , end           );
-LD_SYMBOL ( option_limit         , limit         );
-LD_SYMBOL ( option_reverse       , reverse       );
-LD_SYMBOL ( option_keys          , keys          );
-LD_SYMBOL ( option_values        , values        );
-LD_SYMBOL ( option_keyAsBuffer   , keyAsBuffer   );
-LD_SYMBOL ( option_valueAsBuffer , valueAsBuffer );
+class Database;
+class AsyncWorker;
 
-v8::Handle<v8::Value> CreateIterator (const v8::Arguments& args);
+v8::Local<v8::Value> CreateIterator (const v8::Arguments& args);
 
 class Iterator : public node::ObjectWrap {
 public:
   static void Init ();
-  static v8::Handle<v8::Object> NewInstance (
-      v8::Handle<v8::Object> database
-    , v8::Handle<v8::Number> id
-    , v8::Handle<v8::Object> optionsObj
+  static v8::Local<v8::Object> NewInstance (
+      v8::Local<v8::Object> database
+    , v8::Local<v8::Number> id
+    , v8::Local<v8::Object> optionsObj
   );
 
   Iterator (
@@ -46,7 +41,7 @@ public:
     , bool fillCache
     , bool keyAsBuffer
     , bool valueAsBuffer
-    , v8::Persistent<v8::Value> startPtr
+    , v8::Local<v8::Object> &startHandle
   );
 
   ~Iterator ();
@@ -77,15 +72,13 @@ public:
   AsyncWorker* endWorker;
 
 private:
-  v8::Persistent<v8::Value> startPtr;
+  v8::Persistent<v8::Object> persistentHandle;
 
   bool GetIterator ();
 
-  static v8::Persistent<v8::Function> constructor;
-
-  LD_V8_METHOD( New  )
-  LD_V8_METHOD( Next )
-  LD_V8_METHOD( End  )
+  static NAN_METHOD(New);
+  static NAN_METHOD(Next);
+  static NAN_METHOD(End);
 };
 
 } // namespace leveldown
diff --git a/src/iterator_async.cc b/src/iterator_async.cc
index 5f0e0c8..f8a5873 100644
--- a/src/iterator_async.cc
+++ b/src/iterator_async.cc
@@ -17,7 +17,7 @@ namespace leveldown {
 
 NextWorker::NextWorker (
     Iterator* iterator
-  , v8::Persistent<v8::Function> callback
+  , NanCallback *callback
   , void (*localCallback)(Iterator*)
 ) : AsyncWorker(NULL, callback)
   , iterator(iterator)
@@ -29,23 +29,22 @@ NextWorker::~NextWorker () {}
 void NextWorker::Execute () {
   ok = iterator->IteratorNext(key, value);
   if (!ok)
-    status = iterator->IteratorStatus();
+    SetStatus(iterator->IteratorStatus());
 }
 
 void NextWorker::HandleOKCallback () {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+  NanScope();
 
   v8::Local<v8::Value> returnKey;
   if (iterator->keyAsBuffer) {
-    returnKey = LD_NEW_BUFFER_HANDLE((char*)key.data(), key.size())
+    returnKey = NanNewBufferHandle((char*)key.data(), key.size());
   } else {
     returnKey = v8::String::New((char*)key.data(), key.size());
   }
 
   v8::Local<v8::Value> returnValue;
   if (iterator->valueAsBuffer) {
-    returnValue = LD_NEW_BUFFER_HANDLE((char*)value.data(), value.size());
+    returnValue = NanNewBufferHandle((char*)value.data(), value.size());
   } else {
     returnValue = v8::String::New((char*)value.data(), value.size());
   }
@@ -59,9 +58,9 @@ void NextWorker::HandleOKCallback () {
       , returnKey
       , returnValue
     };
-    LD_RUN_CALLBACK(callback, argv, 3);
+    callback->Run(3, argv);
   } else {
-    LD_RUN_CALLBACK(callback, NULL, 0);
+    callback->Run(0, NULL);
   }
 }
 
@@ -69,7 +68,7 @@ void NextWorker::HandleOKCallback () {
 
 EndWorker::EndWorker (
     Iterator* iterator
-  , v8::Persistent<v8::Function> callback
+  , NanCallback *callback
 ) : AsyncWorker(NULL, callback)
   , iterator(iterator)
 {};
@@ -82,7 +81,7 @@ void EndWorker::Execute () {
 
 void EndWorker::HandleOKCallback () {
   iterator->Release();
-  LD_RUN_CALLBACK(callback, NULL, 0);
+  callback->Run(0, NULL);
 }
 
 } // namespace leveldown
diff --git a/src/iterator_async.h b/src/iterator_async.h
index 1c5e3fb..bbc1fd0 100644
--- a/src/iterator_async.h
+++ b/src/iterator_async.h
@@ -8,6 +8,7 @@
 
 #include <node.h>
 
+#include "nan.h"
 #include "async.h"
 #include "iterator.h"
 
@@ -17,7 +18,7 @@ class NextWorker : public AsyncWorker {
 public:
   NextWorker (
       Iterator* iterator
-    , v8::Persistent<v8::Function> callback
+    , NanCallback *callback
     , void (*localCallback)(Iterator*)
   );
 
@@ -37,7 +38,7 @@ class EndWorker : public AsyncWorker {
 public:
   EndWorker (
       Iterator* iterator
-    , v8::Persistent<v8::Function> callback
+    , NanCallback *callback
   );
 
   virtual ~EndWorker ();
diff --git a/src/leveldown.cc b/src/leveldown.cc
index 5a3fc47..14ee6bd 100644
--- a/src/leveldown.cc
+++ b/src/leveldown.cc
@@ -13,70 +13,64 @@
 
 namespace leveldown {
 
-v8::Handle<v8::Value> DestroyDB (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(DestroyDB) {
+  NanScope();
 
   if (args.Length() < 2) {
-    LD_THROW_RETURN(destroy() requires `location` and `callback` arguments)
+    return NanThrowError("destroy() requires `location` and `callback` arguments");
   }
 
   if (!args[0]->IsString()) {
-    LD_THROW_RETURN(destroy() requires a location string argument)
+    return NanThrowError("destroy() requires a location string argument");
   }
 
   if (!args[1]->IsFunction()) {
-    LD_THROW_RETURN(destroy() requires a callback function argument)
+    return NanThrowError("destroy() requires a callback function argument");
   }
 
-  char* location = FromV8String(args[0]);
+  char* location = NanFromV8String(args[0]);
 
-  v8::Persistent<v8::Function> callback = v8::Persistent<v8::Function>::New(
-      LD_NODE_ISOLATE_PRE
-      v8::Local<v8::Function>::Cast(args[1])
-  );
+  NanCallback* callback = new NanCallback(
+      v8::Local<v8::Function>::Cast(args[1]));
 
   DestroyWorker* worker = new DestroyWorker(
       location
     , callback
   );
 
-  AsyncQueueWorker(worker);
+  NanAsyncQueueWorker(worker);
 
-  return scope.Close(v8::Undefined());
+  NanReturnUndefined();
 }
 
-v8::Handle<v8::Value> RepairDB (const v8::Arguments& args) {
-  LD_NODE_ISOLATE_DECL
-  LD_HANDLESCOPE
+NAN_METHOD(RepairDB) {
+  NanScope();
 
   if (args.Length() < 2) {
-    LD_THROW_RETURN(repair() requires `location` and `callback` arguments)
+    return NanThrowError("repair() requires `location` and `callback` arguments");
   }
 
   if (!args[0]->IsString()) {
-    LD_THROW_RETURN(repair() requires a location string argument)
+    return NanThrowError("repair() requires a location string argument");
   }
 
   if (!args[1]->IsFunction()) {
-    LD_THROW_RETURN(repair() requires a callback function argument)
+    return NanThrowError("repair() requires a callback function argument");
   }
 
-  char* location = FromV8String(args[0]);
+  char* location = NanFromV8String(args[0]);
 
-  v8::Persistent<v8::Function> callback = v8::Persistent<v8::Function>::New(
-      LD_NODE_ISOLATE_PRE
-      v8::Local<v8::Function>::Cast(args[1])
-  );
+ NanCallback* callback = new NanCallback(
+      v8::Local<v8::Function>::Cast(args[1]));
 
   RepairWorker* worker = new RepairWorker(
       location
     , callback
   );
 
-  AsyncQueueWorker(worker);
+  NanAsyncQueueWorker(worker);
 
-  return scope.Close(v8::Undefined());
+  NanReturnUndefined();
 }
 
 void Init (v8::Handle<v8::Object> target) {
@@ -88,16 +82,16 @@ void Init (v8::Handle<v8::Object> target) {
       v8::FunctionTemplate::New(LevelDOWN)->GetFunction();
 
   leveldown->Set(
-      v8::String::NewSymbol("destroy")
+      NanSymbol("destroy")
     , v8::FunctionTemplate::New(DestroyDB)->GetFunction()
   );
 
   leveldown->Set(
-      v8::String::NewSymbol("repair")
+      NanSymbol("repair")
     , v8::FunctionTemplate::New(RepairDB)->GetFunction()
   );
 
-  target->Set(v8::String::NewSymbol("leveldown"), leveldown);
+  target->Set(NanSymbol("leveldown"), leveldown);
 }
 
 NODE_MODULE(leveldown, Init)
diff --git a/src/leveldown.h b/src/leveldown.h
index 371be34..b4e06ec 100644
--- a/src/leveldown.h
+++ b/src/leveldown.h
@@ -9,15 +9,7 @@
 #include <node_buffer.h>
 #include <leveldb/slice.h>
 
-static inline char* FromV8String(v8::Local<v8::Value> from) {
-  size_t sz_;
-  char* to;
-  v8::Local<v8::String> toStr = from->ToString();
-  sz_ = toStr->Utf8Length();
-  to = new char[sz_ + 1];
-  toStr->WriteUtf8(to, -1, NULL, v8::String::NO_OPTIONS);
-  return to;
-}
+#include "nan.h"
 
 static inline size_t StringOrBufferLength(v8::Local<v8::Value> obj) {
   return node::Buffer::HasInstance(obj->ToObject())
@@ -25,86 +17,30 @@ static inline size_t StringOrBufferLength(v8::Local<v8::Value> obj) {
     : obj->ToString()->Utf8Length();
 }
 
-static inline bool BooleanOptionValue(
-      v8::Local<v8::Object> optionsObj
-    , v8::Handle<v8::String> opt) {
-
-  return !optionsObj.IsEmpty()
-    && optionsObj->Has(opt)
-    && optionsObj->Get(opt)->BooleanValue();
-}
-
-static inline bool BooleanOptionValueDefTrue(
-      v8::Local<v8::Object> optionsObj
-    , v8::Handle<v8::String> opt) {
+// NOTE: this MUST be called on objects created by
+// LD_STRING_OR_BUFFER_TO_SLICE
+static inline void DisposeStringOrBufferFromSlice(
+        v8::Persistent<v8::Object> &handle
+      , leveldb::Slice slice) {
 
-  return optionsObj.IsEmpty()
-    || !optionsObj->Has(opt)
-    || optionsObj->Get(opt)->BooleanValue();
+  if (!node::Buffer::HasInstance(NanPersistentToLocal(handle)->Get(NanSymbol("obj"))))
+    delete[] slice.data();
+  NanDispose(handle);
 }
 
-static inline uint32_t UInt32OptionValue(
-      v8::Local<v8::Object> optionsObj
-    , v8::Handle<v8::String> opt
-    , uint32_t def) {
+static inline void DisposeStringOrBufferFromSlice(
+        v8::Local<v8::Object> handle
+      , leveldb::Slice slice) {
 
-  return !optionsObj.IsEmpty()
-    && optionsObj->Has(opt)
-    && optionsObj->Get(opt)->IsUint32()
-      ? optionsObj->Get(opt)->Uint32Value()
-      : def;
+  if (!node::Buffer::HasInstance(handle))
+    delete[] slice.data();
 }
 
-// V8 Isolate stuff introduced with V8 upgrade, see https://github.com/joyent/node/pull/5077
-#if (NODE_MODULE_VERSION > 0x000B)
-#  define LD_NODE_ISOLATE_GET  v8::Isolate::GetCurrent()
-#  define LD_NODE_ISOLATE_DECL v8::Isolate* isolate = LD_NODE_ISOLATE_GET;
-#  define LD_NODE_ISOLATE      isolate 
-#  define LD_NODE_ISOLATE_PRE  isolate, 
-#  define LD_NODE_ISOLATE_POST , isolate 
-#else
-#  define LD_NODE_ISOLATE_GET
-#  define LD_NODE_ISOLATE_DECL
-#  define LD_NODE_ISOLATE
-#  define LD_NODE_ISOLATE_PRE
-#  define LD_NODE_ISOLATE_POST
-#endif
-
-#if (NODE_MODULE_VERSION > 0x000B)
-#  define LD_SYMBOL(var, key)                                                  \
-     static const v8::Persistent<v8::String> var =                             \
-       v8::Persistent<v8::String>::New(                                        \
-          LD_NODE_ISOLATE_GET, v8::String::NewSymbol(#key));
-#  define LD_HANDLESCOPE v8::HandleScope scope(LD_NODE_ISOLATE);
-#  define LD_NEW_BUFFER_HANDLE(data, size) node::Buffer::New(data, size);
-#else
-#  define LD_SYMBOL(var, key)                                                  \
-     static const v8::Persistent<v8::String> var =                             \
-       v8::Persistent<v8::String>::New(v8::String::NewSymbol(#key));
-#  define LD_HANDLESCOPE v8::HandleScope scope;
-#  define LD_NEW_BUFFER_HANDLE(data, size)                                     \
-     v8::Local<v8::Value>::New(node::Buffer::New(data, size)->handle_);
-#endif
-
-#define LD_V8_METHOD(name)                                                     \
-  static v8::Handle<v8::Value> name (const v8::Arguments& args);
-
 #define LD_CB_ERR_IF_NULL_OR_UNDEFINED(thing, name)                            \
   if (thing->IsNull() || thing->IsUndefined()) {                               \
     LD_RETURN_CALLBACK_OR_ERROR(callback, #name " cannot be `null` or `undefined`") \
   }
 
-// NOTE: this MUST be called on objects created by
-// LD_STRING_OR_BUFFER_TO_SLICE
-static inline void DisposeStringOrBufferFromSlice(v8::Persistent<v8::Value> ptr
-      , leveldb::Slice slice) {
-
-  LD_NODE_ISOLATE_DECL
-  if (!node::Buffer::HasInstance(ptr))
-    delete[] slice.data();
-  ptr.Dispose(LD_NODE_ISOLATE);
-}
-
 // NOTE: must call DisposeStringOrBufferFromSlice() on objects created here
 #define LD_STRING_OR_BUFFER_TO_SLICE(to, from, name)                           \
   size_t to ## Sz_;                                                            \
@@ -138,10 +74,9 @@ static inline void DisposeStringOrBufferFromSlice(v8::Persistent<v8::Value> ptr
       )                                                                        \
     };                                                                         \
     LD_RUN_CALLBACK(callback, argv, 1)                                         \
-    return v8::Undefined();                                                    \
+    NanReturnUndefined();                                                      \
   }                                                                            \
-  v8::ThrowException(v8::Exception::Error(v8::String::New(msg)));              \
-  return v8::Undefined();
+  return NanThrowError(msg);
 
 #define LD_RUN_CALLBACK(callback, argv, length)                                \
   v8::TryCatch try_catch;                                                      \
@@ -150,35 +85,30 @@ static inline void DisposeStringOrBufferFromSlice(v8::Persistent<v8::Value> ptr
     node::FatalException(try_catch);                                           \
   }
 
-#define LD_THROW_RETURN(...)                                                   \
-  v8::ThrowException(v8::Exception::Error(v8::String::New(#__VA_ARGS__)));     \
-  return v8::Undefined();
-
 /* LD_METHOD_SETUP_COMMON setup the following objects:
  *  - Database* database
  *  - v8::Local<v8::Object> optionsObj (may be empty)
  *  - v8::Persistent<v8::Function> callback (won't be empty)
- * Will LD_THROW_RETURN if there isn't a callback in arg 0 or 1
+ * Will throw/return if there isn't a callback in arg 0 or 1
  */
 #define LD_METHOD_SETUP_COMMON(name, optionPos, callbackPos)                   \
-  if (args.Length() == 0) {                                                    \
-    LD_THROW_RETURN(name() requires a callback argument)                       \
-  }                                                                            \
+  if (args.Length() == 0)                                                      \
+    return NanThrowError(#name "() requires a callback argument");             \
   leveldown::Database* database =                                              \
     node::ObjectWrap::Unwrap<leveldown::Database>(args.This());                \
   v8::Local<v8::Object> optionsObj;                                            \
   v8::Local<v8::Function> callback;                                            \
   if (optionPos == -1 && args[callbackPos]->IsFunction()) {                    \
-    callback = v8::Local<v8::Function>::Cast(args[callbackPos]);               \
+    callback = args[callbackPos].As<v8::Function>();                           \
   } else if (optionPos != -1 && args[callbackPos - 1]->IsFunction()) {         \
-    callback = v8::Local<v8::Function>::Cast(args[callbackPos - 1]);           \
+    callback = args[callbackPos - 1].As<v8::Function>();                       \
   } else if (optionPos != -1                                                   \
         && args[optionPos]->IsObject()                                         \
         && args[callbackPos]->IsFunction()) {                                  \
-    optionsObj = v8::Local<v8::Object>::Cast(args[optionPos]);                 \
-    callback = v8::Local<v8::Function>::Cast(args[callbackPos]);               \
+    optionsObj = args[optionPos].As<v8::Object>();                             \
+    callback = args[callbackPos].As<v8::Function>();                           \
   } else {                                                                     \
-    LD_THROW_RETURN(name() requires a callback argument)                       \
+    return NanThrowError(#name "() requires a callback argument");             \
   }
 
 #define LD_METHOD_SETUP_COMMON_ONEARG(name) LD_METHOD_SETUP_COMMON(name, -1, 0)
diff --git a/src/leveldown_async.cc b/src/leveldown_async.cc
index 008f425..db84c1f 100644
--- a/src/leveldown_async.cc
+++ b/src/leveldown_async.cc
@@ -14,7 +14,7 @@ namespace leveldown {
 
 DestroyWorker::DestroyWorker (
     char* location
-  , v8::Persistent<v8::Function> callback
+  , NanCallback *callback
 ) : AsyncWorker(NULL, callback)
   , location(location)
 {};
@@ -25,14 +25,14 @@ DestroyWorker::~DestroyWorker () {
 
 void DestroyWorker::Execute () {
   leveldb::Options options;
-  status = leveldb::DestroyDB(location, options);
+  SetStatus(leveldb::DestroyDB(location, options));
 }
 
 /** REPAIR WORKER **/
 
 RepairWorker::RepairWorker (
     char* location
-  , v8::Persistent<v8::Function> callback
+  , NanCallback *callback
 ) : AsyncWorker(NULL, callback)
   , location(location)
 {};
@@ -43,7 +43,7 @@ RepairWorker::~RepairWorker () {
 
 void RepairWorker::Execute () {
   leveldb::Options options;
-  status = leveldb::RepairDB(location, options);
+  SetStatus(leveldb::RepairDB(location, options));
 }
 
 } // namespace leveldown
diff --git a/src/leveldown_async.h b/src/leveldown_async.h
index 6033769..d045a81 100644
--- a/src/leveldown_async.h
+++ b/src/leveldown_async.h
@@ -16,7 +16,7 @@ class DestroyWorker : public AsyncWorker {
 public:
   DestroyWorker (
       char* location
-    , v8::Persistent<v8::Function> callback
+    , NanCallback *callback
   );
 
   virtual ~DestroyWorker ();
@@ -30,7 +30,7 @@ class RepairWorker : public AsyncWorker {
 public:
   RepairWorker (
       char* location
-    , v8::Persistent<v8::Function> callback
+    , NanCallback *callback
   );
 
   virtual ~RepairWorker ();
diff --git a/src/nan.h b/src/nan.h
new file mode 120000
index 0000000..b4f9768
--- /dev/null
+++ b/src/nan.h
@@ -0,0 +1 @@
+../../nan/nan.h
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-leveldown.git



More information about the Pkg-javascript-commits mailing list