[Pkg-javascript-commits] [node-leveldown] 01/05: Imported Upstream version 1.4.1+dfsg

Felipe Sateler fsateler at moszumanska.debian.org
Tue Dec 15 00:24:18 UTC 2015


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

fsateler pushed a commit to branch master
in repository node-leveldown.

commit dec801f29059e505fe217e09a802acc2617ca3e9
Author: Felipe Sateler <fsateler at debian.org>
Date:   Sun Oct 11 11:53:12 2015 -0300

    Imported Upstream version 1.4.1+dfsg
---
 .dntrc                   |  18 +--
 .gitignore               |   3 +
 .npmignore               |   1 +
 .prebuildrc              |  17 +++
 .travis.yml              |  35 ++----
 CHANGELOG.md             |  30 +++++
 CONTRIBUTING.md          |  27 -----
 README.md                |  39 +++----
 iterator.js              |   6 +
 leveldown.js             |   4 +-
 package.json             |  14 ++-
 src/async.h              |  10 +-
 src/batch.cc             |  91 +++++++--------
 src/batch.h              |   8 +-
 src/batch_async.cc       |   2 +-
 src/batch_async.h        |   2 +-
 src/common.h             |  36 ++++++
 src/database.cc          | 297 ++++++++++++++++++-----------------------------
 src/database.h           |  23 ++--
 src/database_async.cc    |  53 +++++----
 src/database_async.h     |  16 +--
 src/iterator.cc          | 228 +++++++++++++++++++++---------------
 src/iterator.h           |   6 +-
 src/iterator_async.cc    |  26 +++--
 src/iterator_async.h     |   4 +-
 src/leveldown.cc         |  38 +++---
 src/leveldown.h          |  46 ++++----
 src/leveldown_async.cc   |   8 +-
 src/leveldown_async.h    |  12 +-
 test/compression-test.js |  92 +++++++++++++++
 test/iterator-test.js    |  63 ++++++++++
 31 files changed, 717 insertions(+), 538 deletions(-)

diff --git a/.dntrc b/.dntrc
index a956f18..eba4b97 100644
--- a/.dntrc
+++ b/.dntrc
@@ -2,18 +2,22 @@
 ## see https://github.com/rvagg/dnt
 
 NODE_VERSIONS="\
-  v0.10.31     \
-  v0.11.13     \
+  v0.10.40     \
+  v0.12.7      \
 "
 IOJS_VERSIONS="\
-  v1.0.1-release \
+  v1.8.4 \
+  v2.0.1 \
+  v2.3.4 \
+  v3.0.0-rc.3 \
 "
 OUTPUT_PREFIX="leveldown-"
 TEST_CMD="\
   cd /dnt/ &&                                                    \
   npm install &&                                                 \
-  node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js \
-      --nodedir /usr/src/node/ rebuild &&                        \
-  node_modules/.bin/tap test/*-test.js;                          \
+  npm run-script prebuild                                        \
+      --nodedir=/usr/src/node/ &&                                \
+  node_modules/.bin/tape test/*-test.js                          \
 "
-
+# for tape
+LOG_OK_CMD="tail -2 | head -1 | sed 's/^# //'"
diff --git a/.gitignore b/.gitignore
index 43b07bd..406eada 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 node_modules/
 build/
+build-pre-gyp/
 libleveldb.so
 libleveldb.a
 leakydb
@@ -11,3 +12,5 @@ bench/
 *.obj
 *.1sdk.pdb
 *.lastbuildstate
+npm-debug.log
+prebuilds/
diff --git a/.npmignore b/.npmignore
index 193ad72..25b2553 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,5 +1,6 @@
 *.tar.gz
 build/
+build-pre-gyp/
 test-data.tar
 test-data.db.tar
 deps/leveldb/leveldb-basho/
diff --git a/.prebuildrc b/.prebuildrc
new file mode 100644
index 0000000..55d59d2
--- /dev/null
+++ b/.prebuildrc
@@ -0,0 +1,17 @@
+# abi 11
+target[] = 0.10.40
+
+# abi 14
+target[] = 0.12.7
+
+# abi 42
+target[] = 1.0.4
+
+# abi 43
+target[] = 1.8.4
+
+# abi 44
+target[] = 2.4.0
+
+# abi 45
+target[] = 3.0.0
diff --git a/.travis.yml b/.travis.yml
index d928457..f28850b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,30 +1,19 @@
-language: c
+language: node_js
 
 before_install:
-  - rm -rf ~/.nvm
-  - wget https://raw.githubusercontent.com/visionmedia/n/master/bin/n -qO n
-  - chmod +x n
-  - sudo cp n /usr/local/bin/n
-  - sudo chmod -R a+xw /usr/local
-  - n --version
+  - export JOBS=max
+  - export prebuild_compile=true
 
-script:
-  - n 0.10
-  - node -v; which node; npm -v; which npm
-  - JOBS=max npm install
-  - npm test && rm -rf node_modules/
+node_js:
+  - "2.4"
+  - "1.8"
+  - "1.0"
+  - "0.12"
+  - "0.10"
 
-  - n latest
-  - node -v; which node; npm -v; which npm
-  - JOBS=max npm install
-  - npm test && rm -rf node_modules/
+install:
+  - npm install
 
-  - n io latest
-  - iojs -v; which iojs; npm -v; which npm
-  - JOBS=max npm install
+script:
   - npm test
 
-notifications:
-  email:
-    - rod at vagg.org
-    - ralphtheninja at riseup.net
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 246d275..8865dba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,33 @@
+Note that we have filtered out commits related to new tags, updating changelog and we're also not listing any merge commits, i.e. we are only listing things that changed between versions.
+
+### 1.0.7 May 27 2015
+
+ * [[`61398a0056`](https://github.com/level/leveldown/commit/61398a0056)] - link to level/community (Lars-Magnus Skog)
+ * [[`382a1a7fa3`](https://github.com/level/leveldown/commit/382a1a7fa3)] - add compression test suite (Julian Gruber)
+ * [[`139db7bc7f`](https://github.com/level/leveldown/commit/139db7bc7f)] - use const reference instead of by value in Database constructor (Lars-Magnus Skog)
+ * [[`b56a86323e`](https://github.com/level/leveldown/commit/b56a86323e)] - refactor NanNew() on strings into option value functions (Lars-Magnus Skog)
+ * [[`ca1f4746c4`](https://github.com/level/leveldown/commit/ca1f4746c4)] - refactor BooleanOptionValue (Lars-Magnus Skog)
+ * [[`56def2d7c8`](https://github.com/level/leveldown/commit/56def2d7c8)] - NanUInt32OptionValue -> UInt32OptionValue (Lars-Magnus Skog)
+ * [[`39c614a24f`](https://github.com/level/leveldown/commit/39c614a24f)] - NanBooleanOptionValue -> BooleanOptionValue (Lars-Magnus Skog)
+ * [[`fcdc46183e`](https://github.com/level/leveldown/commit/fcdc46183e)] - simplify location logic, let Database take care of allocation (Lars-Magnus Skog)
+ * [[`8cb90e6b6d`](https://github.com/level/leveldown/commit/8cb90e6b6d)] - update abstract-leveldown (Lars-Magnus Skog)
+ * [[`f70b6576e7`](https://github.com/level/leveldown/commit/f70b6576e7)] - update .travis.yml (nvm works on travis now) (Lars-Magnus Skog)
+ * [[`007550e7f7`](https://github.com/level/leveldown/commit/007550e7f7)] - 1.0.6 (Lars-Magnus Skog)
+
+### 1.0.5/1.0.6 May 5 2015
+
+* [[`9064099fe7`](https://github.com/level/leveldown/commit/9064099fe7)] - pass db to abstractIterator so gc keeps it (Julian Gruber)
+
+### 1.0.4 May 5 2015
+
+ * [[`b550c98291`](https://github.com/level/leveldown/commit/b550c98291)] - update nan for iojs 2.0.0 (Lars-Magnus Skog)
+
+### 1.0.3 May 2 2015
+
+ * [[`82479b689f`](https://github.com/level/leveldown/commit/82479b689f)] - tap -> tape + faucet (Lars-Magnus Skog)
+ * [[`ca9101542a`](https://github.com/level/leveldown/commit/ca9101542a)] - fix write-random.js, use leveldown instead of lmdb (Lars-Magnus Skog)
+ * [[`03fbbfb99f`](https://github.com/level/leveldown/commit/03fbbfb99f)] - fix bench/db-bench.js (Lars-Magnus Skog)
+
 ### 1.0.2 Apr 26 2015
   * [[`8470a63678`](https://github.com/level/leveldown/commit/8470a63678)] - s/rvagg\/node-/level\// (Lars-Magnus Skog)
   * [[`9cbf592bea`](https://github.com/level/leveldown/commit/9cbf592bea)] - add documentation about snapshots (Max Ogden)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 0ed7099..0000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# LevelDOWN is an OPEN Open Source Project
-
------------------------------------------
-
-## What?
-
-Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
-
-## Rules
-
-There are a few basic ground-rules for contributors:
-
-1. **No `--force` pushes** or modifying the Git history in any way.
-1. **Non-master branches** ought to be used for ongoing work.
-1. **External API changes and significant modifications** ought to be subject to an **internal pull-request** to solicit feedback from other contributors.
-1. Internal pull-requests to solicit feedback are *encouraged* for any other non-trivial contribution but left to the discretion of the contributor.
-1. Contributors should attempt to adhere to the prevailing code-style.
-
-## Releases
-
-Declaring formal releases remains the prerogative of the project maintainer.
-
-## Changes to this arrangement
-
-This is an experiment and feedback is welcome! This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change.
-
------------------------------------------
diff --git a/README.md b/README.md
index a79f0cd..6af6a89 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,7 @@ Tested & supported platforms
   * <a href="#leveldown_getProperty"><code><b>leveldown#getProperty()</b></code></a>
   * <a href="#leveldown_iterator"><code><b>leveldown#iterator()</b></code></a>
   * <a href="#iterator_next"><code><b>iterator#next()</b></code></a>
+  * <a href="#iterator_seek"><code><b>iterator#seek()</b></code></a>
   * <a href="#iterator_end"><code><b>iterator#end()</b></code></a>
   * <a href="#leveldown_destroy"><code><b>leveldown.destroy()</b></code></a>
   * <a href="#leveldown_repair"><code><b>leveldown.repair()</b></code></a>
@@ -230,6 +231,13 @@ Otherwise, the `callback` function will be called with the following 3 arguments
 
 
 --------------------------------------------------------
+<a name="iterator_seek"></a>
+### iterator#seek(key)
+<code>seek()</code> is an instance method on an existing iterator object, used to seek the underlying LevelDB iterator to a given key.
+
+By calling <code>seek(key)</code>, subsequent calls to <code>next(cb)</code> will return key/values larger or smaller than key, based on your <code>reverse</code> setting in the iterator constructor.
+
+--------------------------------------------------------
 <a name="iterator_end"></a>
 ### iterator#end(callback)
 <code>end()</code> is an instance method on an existing iterator object. The underlying LevelDB iterator will be deleted and the `callback` function will be called with no arguments if the operation is successful or with a single `error` argument if the operation failed for any reason.
@@ -289,39 +297,24 @@ LevelDOWN is an **OPEN Open Source Project**. This means that:
 
 > Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
 
-See the [CONTRIBUTING.md](https://github.com/level/leveldown/blob/master/CONTRIBUTING.md) file for more details.
-
-### Contributors
-
-LevelDOWN is only possible due to the excellent work of the following contributors:
-
-<table><tbody>
-<tr><th align="left">Rod Vagg</th><td><a href="https://github.com/rvagg">GitHub/rvagg</a></td><td><a href="http://twitter.com/rvagg">Twitter/@rvagg</a></td></tr>
-<tr><th align="left">John Chesley</th><td><a href="https://github.com/chesles/">GitHub/chesles</a></td><td><a href="http://twitter.com/chesles">Twitter/@chesles</a></td></tr>
-<tr><th align="left">Jake Verbaten</th><td><a href="https://github.com/raynos">GitHub/raynos</a></td><td><a href="http://twitter.com/raynos2">Twitter/@raynos2</a></td></tr>
-<tr><th align="left">Dominic Tarr</th><td><a href="https://github.com/dominictarr">GitHub/dominictarr</a></td><td><a href="http://twitter.com/dominictarr">Twitter/@dominictarr</a></td></tr>
-<tr><th align="left">Max Ogden</th><td><a href="https://github.com/maxogden">GitHub/maxogden</a></td><td><a href="http://twitter.com/maxogden">Twitter/@maxogden</a></td></tr>
-<tr><th align="left">Lars-Magnus Skog</th><td><a href="https://github.com/ralphtheninja">GitHub/ralphtheninja</a></td><td><a href="http://twitter.com/ralphtheninja">Twitter/@ralphtheninja</a></td></tr>
-<tr><th align="left">David Björklund</th><td><a href="https://github.com/kesla">GitHub/kesla</a></td><td><a href="http://twitter.com/david_bjorklund">Twitter/@david_bjorklund</a></td></tr>
-<tr><th align="left">Julian Gruber</th><td><a href="https://github.com/juliangruber">GitHub/juliangruber</a></td><td><a href="http://twitter.com/juliangruber">Twitter/@juliangruber</a></td></tr>
-<tr><th align="left">Paolo Fragomeni</th><td><a href="https://github.com/hij1nx">GitHub/hij1nx</a></td><td><a href="http://twitter.com/hij1nx">Twitter/@hij1nx</a></td></tr>
-<tr><th align="left">Anton Whalley</th><td><a href="https://github.com/No9">GitHub/No9</a></td><td><a href="https://twitter.com/antonwhalley">Twitter/@antonwhalley</a></td></tr>
-<tr><th align="left">Matteo Collina</th><td><a href="https://github.com/mcollina">GitHub/mcollina</a></td><td><a href="https://twitter.com/matteocollina">Twitter/@matteocollina</a></td></tr>
-<tr><th align="left">Pedro Teixeira</th><td><a href="https://github.com/pgte">GitHub/pgte</a></td><td><a href="https://twitter.com/pgte">Twitter/@pgte</a></td></tr>
-<tr><th align="left">James Halliday</th><td><a href="https://github.com/substack">GitHub/substack</a></td><td><a href="https://twitter.com/substack">Twitter/@substack</a></td></tr>
-</tbody></table>
+See the [contribution guide](https://github.com/Level/community/blob/master/CONTRIBUTING.md) for more details.
 
 ### Windows
 
 A large portion of the Windows support comes from code by [Krzysztof Kowalczyk](http://blog.kowalczyk.info/) [@kjk](https://twitter.com/kjk), see his Windows LevelDB port [here](http://code.google.com/r/kkowalczyk-leveldb/). If you're using LevelUP on Windows, you should give him your thanks!
 
 
+Prebuilt binaries
+-----------------
+
+LevelDOWN uses `node-pre-gyp` to support prebuilt binaries. For a list of supported prebuilt platform binaries see https://github.com/Level/leveldown/releases
+
 <a name="license"></a>
 License & copyright
 -------------------
 
-Copyright (c) 2012-2015 LevelDOWN contributors (listed above).
+Copyright © 2012-2015 **LevelDOWN** [contributors](https://github.com/level/community#contributors).
 
-LevelDOWN is licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE.md file for more details.
+**LevelDOWN** is licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included `LICENSE.md` file for more details.
 
 *LevelDOWN builds on the excellent work of the LevelDB and Snappy teams from Google and additional contributors. LevelDB and Snappy are both issued under the [New BSD Licence](http://opensource.org/licenses/BSD-3-Clause).*
diff --git a/iterator.js b/iterator.js
index f3f5c1e..4c8c3a7 100644
--- a/iterator.js
+++ b/iterator.js
@@ -13,6 +13,12 @@ function Iterator (db, options) {
 
 util.inherits(Iterator, AbstractIterator)
 
+Iterator.prototype.seek = function (key) {
+  if (typeof key !== 'string')
+    throw new Error('seek requires a string key')
+  this.cache = null
+  this.binding.seek(key)
+}
 
 Iterator.prototype._next = function (callback) {
   var that = this
diff --git a/leveldown.js b/leveldown.js
index a058088..beb1e4c 100644
--- a/leveldown.js
+++ b/leveldown.js
@@ -1,7 +1,7 @@
 const util              = require('util')
     , AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN
 
-    , binding           = require('bindings')('leveldown.node').leveldown
+    , binding           = require('bindings')('leveldown').leveldown
 
     , ChainedBatch      = require('./chained-batch')
     , Iterator          = require('./iterator')
@@ -99,4 +99,4 @@ LevelDOWN.repair = function (location, callback) {
 }
 
 
-module.exports = LevelDOWN
\ No newline at end of file
+module.exports = LevelDOWN
diff --git a/package.json b/package.json
index 3d6d03e..346864c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "leveldown",
   "description": "A Node.js LevelDB binding, primary backend for LevelUP",
-  "version": "1.0.6",
+  "version": "1.4.1",
   "contributors": [
     "Rod Vagg <r at va.gg> (https://github.com/rvagg)",
     "John Chesley <john at chesl.es> (https://github.com/chesles/)",
@@ -28,17 +28,19 @@
   ],
   "main": "leveldown.js",
   "dependencies": {
-    "abstract-leveldown": "~2.1.0",
+    "abstract-leveldown": "~2.4.0",
     "bindings": "~1.2.1",
     "fast-future": "~1.0.0",
-    "nan": "~1.8.4"
+    "nan": "~2.0.0",
+    "prebuild": "~2.3.3"
   },
   "devDependencies": {
+    "async": "~1.0.0",
+    "delayed": "~1.0.1",
     "du": "~0.1.0",
     "faucet": "0.0.1",
     "mkfiletree": "~0.0.1",
     "monotonic-timestamp": "~0.0.8",
-    "node-gyp": "~1.0.1",
     "node-uuid": "~1.4.3",
     "optimist": "~0.6.1",
     "readfiletree": "~0.0.1",
@@ -47,7 +49,9 @@
     "tape": "~4.0.0"
   },
   "scripts": {
-    "test": "tape test/*-test.js | faucet"
+    "install": "prebuild --download",
+    "test": "tape test/*-test.js | faucet",
+    "prebuild": "prebuild --verbose"
   },
   "license": "MIT",
   "gypfile": true
diff --git a/src/async.h b/src/async.h
index 54bf40c..bcce316 100644
--- a/src/async.h
+++ b/src/async.h
@@ -14,16 +14,12 @@ namespace leveldown {
 
 class Database;
 
-/* abstract */ class AsyncWorker : public NanAsyncWorker {
+/* abstract */ class AsyncWorker : public Nan::AsyncWorker {
 public:
   AsyncWorker (
       leveldown::Database* database
-    , NanCallback *callback
-  ) : NanAsyncWorker(callback), database(database) {
-    NanScope();
-    v8::Local<v8::Object> obj = NanNew<v8::Object>();
-    NanAssignPersistent(persistentHandle, obj);
-  }
+    , Nan::Callback *callback
+  ) : Nan::AsyncWorker(callback), database(database) { }
 
 protected:
   void SetStatus(leveldb::Status status) {
diff --git a/src/batch.cc b/src/batch.cc
index 32dfbe3..23a8a3d 100644
--- a/src/batch.cc
+++ b/src/batch.cc
@@ -5,10 +5,11 @@
 #include "database.h"
 #include "batch_async.h"
 #include "batch.h"
+#include "common.h"
 
 namespace leveldown {
 
-static v8::Persistent<v8::FunctionTemplate> batch_constructor;
+static Nan::Persistent<v8::FunctionTemplate> batch_constructor;
 
 Batch::Batch (leveldown::Database* database, bool sync) : database(database) {
   options = new leveldb::WriteOptions();
@@ -27,65 +28,61 @@ leveldb::Status Batch::Write () {
 }
 
 void Batch::Init () {
-  v8::Local<v8::FunctionTemplate> tpl = NanNew<v8::FunctionTemplate>(Batch::New);
-  NanAssignPersistent(batch_constructor, tpl);
-  tpl->SetClassName(NanNew("Batch"));
+  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(Batch::New);
+  batch_constructor.Reset(tpl);
+  tpl->SetClassName(Nan::New("Batch").ToLocalChecked());
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
-  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);
+  Nan::SetPrototypeMethod(tpl, "put", Batch::Put);
+  Nan::SetPrototypeMethod(tpl, "del", Batch::Del);
+  Nan::SetPrototypeMethod(tpl, "clear", Batch::Clear);
+  Nan::SetPrototypeMethod(tpl, "write", Batch::Write);
 }
 
 NAN_METHOD(Batch::New) {
-  NanScope();
-
-  Database* database = node::ObjectWrap::Unwrap<Database>(args[0]->ToObject());
+  Database* database = Nan::ObjectWrap::Unwrap<Database>(info[0]->ToObject());
   v8::Local<v8::Object> optionsObj;
 
-  if (args.Length() > 1 && args[1]->IsObject()) {
-    optionsObj = v8::Local<v8::Object>::Cast(args[1]);
+  if (info.Length() > 1 && info[1]->IsObject()) {
+    optionsObj = v8::Local<v8::Object>::Cast(info[1]);
   }
 
-  bool sync = NanBooleanOptionValue(optionsObj, NanNew("sync"));
+  bool sync = BooleanOptionValue(optionsObj, "sync");
 
   Batch* batch = new Batch(database, sync);
-  batch->Wrap(args.This());
+  batch->Wrap(info.This());
 
-  NanReturnValue(args.This());
+  info.GetReturnValue().Set(info.This());
 }
 
-v8::Handle<v8::Value> Batch::NewInstance (
-        v8::Handle<v8::Object> database
-      , v8::Handle<v8::Object> optionsObj
+v8::Local<v8::Value> Batch::NewInstance (
+        v8::Local<v8::Object> database
+      , v8::Local<v8::Object> optionsObj
     ) {
 
-  NanEscapableScope();
+  Nan::EscapableHandleScope scope;
 
   v8::Local<v8::Object> instance;
 
   v8::Local<v8::FunctionTemplate> constructorHandle =
-      NanNew<v8::FunctionTemplate>(batch_constructor);
+      Nan::New<v8::FunctionTemplate>(batch_constructor);
 
   if (optionsObj.IsEmpty()) {
-    v8::Handle<v8::Value> argv[1] = { database };
+    v8::Local<v8::Value> argv[1] = { database };
     instance = constructorHandle->GetFunction()->NewInstance(1, argv);
   } else {
-    v8::Handle<v8::Value> argv[2] = { database, optionsObj };
+    v8::Local<v8::Value> argv[2] = { database, optionsObj };
     instance = constructorHandle->GetFunction()->NewInstance(2, argv);
   }
 
-  return NanEscapeScope(instance);
+  return scope.Escape(instance);
 }
 
 NAN_METHOD(Batch::Put) {
-  NanScope();
-
-  Batch* batch = ObjectWrap::Unwrap<Batch>(args.Holder());
-  v8::Handle<v8::Function> callback; // purely for the error macros
+  Batch* batch = ObjectWrap::Unwrap<Batch>(info.Holder());
+  v8::Local<v8::Function> callback; // purely for the error macros
 
-  v8::Local<v8::Value> keyBuffer = args[0];
-  v8::Local<v8::Value> valueBuffer = args[1];
+  v8::Local<v8::Value> keyBuffer = info[0];
+  v8::Local<v8::Value> valueBuffer = info[1];
   LD_STRING_OR_BUFFER_TO_SLICE(key, keyBuffer, key)
   LD_STRING_OR_BUFFER_TO_SLICE(value, valueBuffer, value)
 
@@ -96,17 +93,15 @@ NAN_METHOD(Batch::Put) {
   DisposeStringOrBufferFromSlice(keyBuffer, key);
   DisposeStringOrBufferFromSlice(valueBuffer, value);
 
-  NanReturnValue(args.Holder());
+  info.GetReturnValue().Set(info.Holder());
 }
 
 NAN_METHOD(Batch::Del) {
-  NanScope();
-
-  Batch* batch = ObjectWrap::Unwrap<Batch>(args.Holder());
+  Batch* batch = ObjectWrap::Unwrap<Batch>(info.Holder());
 
-  v8::Handle<v8::Function> callback; // purely for the error macros
+  v8::Local<v8::Function> callback; // purely for the error macros
 
-  v8::Local<v8::Value> keyBuffer = args[0];
+  v8::Local<v8::Value> keyBuffer = info[0];
   LD_STRING_OR_BUFFER_TO_SLICE(key, keyBuffer, key)
 
   batch->batch->Delete(key);
@@ -115,38 +110,32 @@ NAN_METHOD(Batch::Del) {
 
   DisposeStringOrBufferFromSlice(keyBuffer, key);
 
-  NanReturnValue(args.Holder());
+  info.GetReturnValue().Set(info.Holder());
 }
 
 NAN_METHOD(Batch::Clear) {
-  NanScope();
-
-  Batch* batch = ObjectWrap::Unwrap<Batch>(args.Holder());
+  Batch* batch = ObjectWrap::Unwrap<Batch>(info.Holder());
 
   batch->batch->Clear();
   batch->hasData = false;
 
-  NanReturnValue(args.Holder());
+  info.GetReturnValue().Set(info.Holder());
 }
 
 NAN_METHOD(Batch::Write) {
-  NanScope();
-
-  Batch* batch = ObjectWrap::Unwrap<Batch>(args.Holder());
+  Batch* batch = ObjectWrap::Unwrap<Batch>(info.Holder());
 
   if (batch->hasData) {
-    NanCallback *callback =
-        new NanCallback(v8::Local<v8::Function>::Cast(args[0]));
+    Nan::Callback *callback =
+        new Nan::Callback(v8::Local<v8::Function>::Cast(info[0]));
     BatchWriteWorker* worker  = new BatchWriteWorker(batch, callback);
     // persist to prevent accidental GC
-    v8::Local<v8::Object> _this = args.This();
+    v8::Local<v8::Object> _this = info.This();
     worker->SaveToPersistent("batch", _this);
-    NanAsyncQueueWorker(worker);
+    Nan::AsyncQueueWorker(worker);
   } else {
-    LD_RUN_CALLBACK(v8::Local<v8::Function>::Cast(args[0]), 0, NULL);
+    LD_RUN_CALLBACK(v8::Local<v8::Function>::Cast(info[0]), 0, NULL);
   }
-
-  NanReturnUndefined();
 }
 
 } // namespace leveldown
diff --git a/src/batch.h b/src/batch.h
index b2b1880..39fb068 100644
--- a/src/batch.h
+++ b/src/batch.h
@@ -10,12 +10,12 @@
 
 namespace leveldown {
 
-class Batch : public node::ObjectWrap {
+class Batch : public Nan::ObjectWrap {
 public:
   static void Init();
-  static v8::Handle<v8::Value> NewInstance (
-      v8::Handle<v8::Object> database
-    , v8::Handle<v8::Object> optionsObj
+  static v8::Local<v8::Value> NewInstance (
+      v8::Local<v8::Object> database
+    , v8::Local<v8::Object> optionsObj
   );
 
   Batch  (leveldown::Database* database, bool sync);
diff --git a/src/batch_async.cc b/src/batch_async.cc
index c386319..f840f24 100644
--- a/src/batch_async.cc
+++ b/src/batch_async.cc
@@ -14,7 +14,7 @@ namespace leveldown {
 
 BatchWriteWorker::BatchWriteWorker (
     Batch* batch
-  , NanCallback *callback
+  , Nan::Callback *callback
 ) : AsyncWorker(NULL, callback)
   , batch(batch)
 {};
diff --git a/src/batch_async.h b/src/batch_async.h
index 218591f..72587b9 100644
--- a/src/batch_async.h
+++ b/src/batch_async.h
@@ -19,7 +19,7 @@ class BatchWriteWorker : public AsyncWorker {
 public:
   BatchWriteWorker (
       Batch* batch
-    , NanCallback *callback
+    , Nan::Callback *callback
   );
 
   virtual ~BatchWriteWorker ();
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..1eca681
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2012-2015 LevelDOWN contributors
+ * See list at <https://github.com/level/leveldown#contributing>
+ * MIT License <https://github.com/level/leveldown/blob/master/LICENSE.md>
+ */
+
+#ifndef LD_COMMON_H
+#define LD_COMMON_H
+
+#include <nan.h>
+
+namespace leveldown {
+
+NAN_INLINE bool BooleanOptionValue(v8::Local<v8::Object> options,
+                                   const char* _key,
+                                   bool def = false) {
+  v8::Local<v8::String> key = Nan::New(_key).ToLocalChecked();
+  return !options.IsEmpty()
+    && options->Has(key)
+    ? options->Get(key)->BooleanValue()
+    : def;
+}
+
+NAN_INLINE uint32_t UInt32OptionValue(v8::Local<v8::Object> options,
+                                      const char* _key,
+                                      uint32_t def) {
+  v8::Local<v8::String> key = Nan::New(_key).ToLocalChecked();
+  return !options.IsEmpty()
+    && options->Has(key)
+    && options->Get(key)->IsNumber()
+    ? options->Get(key)->Uint32Value()
+    : def;
+}
+
+} // namespace leveldown
+
+#endif
diff --git a/src/database.cc b/src/database.cc
index 2f6497a..c3ea44b 100644
--- a/src/database.cc
+++ b/src/database.cc
@@ -15,18 +15,19 @@
 #include "database_async.h"
 #include "batch.h"
 #include "iterator.h"
+#include "common.h"
 
 namespace leveldown {
 
-static v8::Persistent<v8::FunctionTemplate> database_constructor;
+static Nan::Persistent<v8::FunctionTemplate> database_constructor;
 
-Database::Database (NanUtf8String* location) : location(location) {
-  db = NULL;
-  currentIteratorId = 0;
-  pendingCloseWorker = NULL;
-  blockCache = NULL;
-  filterPolicy = NULL;
-};
+Database::Database (const v8::Local<v8::Value>& from)
+  : location(new Nan::Utf8String(from))
+  , db(NULL)
+  , currentIteratorId(0)
+  , pendingCloseWorker(NULL)
+  , blockCache(NULL)
+  , filterPolicy(NULL) {};
 
 Database::~Database () {
   if (db != NULL)
@@ -34,15 +35,12 @@ Database::~Database () {
   delete location;
 };
 
-NanUtf8String* Database::Location() { return location; }
-
 /* Calls from worker threads, NO V8 HERE *****************************/
 
 leveldb::Status Database::OpenDatabase (
         leveldb::Options* options
-      , std::string location
     ) {
-  return leveldb::DB::Open(*options, location, &db);
+  return leveldb::DB::Open(*options, **location, &db);
 }
 
 leveldb::Status Database::PutToDatabase (
@@ -108,7 +106,7 @@ void Database::ReleaseIterator (uint32_t id) {
   // iterators to end before we can close them
   iterators.erase(id);
   if (iterators.empty() && pendingCloseWorker != NULL) {
-    NanAsyncQueueWorker((AsyncWorker*)pendingCloseWorker);
+    Nan::AsyncQueueWorker((AsyncWorker*)pendingCloseWorker);
     pendingCloseWorker = NULL;
   }
 }
@@ -129,97 +127,65 @@ void Database::CloseDatabase () {
 /* V8 exposed functions *****************************/
 
 NAN_METHOD(LevelDOWN) {
-  NanScope();
-
-  v8::Local<v8::String> location;
-  if (args.Length() != 0 && args[0]->IsString())
-    location = args[0].As<v8::String>();
-  NanReturnValue(Database::NewInstance(location));
+  v8::Local<v8::String> location = info[0].As<v8::String>();
+  info.GetReturnValue().Set(Database::NewInstance(location));
 }
 
 void Database::Init () {
-  v8::Local<v8::FunctionTemplate> tpl = NanNew<v8::FunctionTemplate>(Database::New);
-  NanAssignPersistent(database_constructor, tpl);
-  tpl->SetClassName(NanNew("Database"));
+  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(Database::New);
+  database_constructor.Reset(tpl);
+  tpl->SetClassName(Nan::New("Database").ToLocalChecked());
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
-  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);
+  Nan::SetPrototypeMethod(tpl, "open", Database::Open);
+  Nan::SetPrototypeMethod(tpl, "close", Database::Close);
+  Nan::SetPrototypeMethod(tpl, "put", Database::Put);
+  Nan::SetPrototypeMethod(tpl, "get", Database::Get);
+  Nan::SetPrototypeMethod(tpl, "del", Database::Delete);
+  Nan::SetPrototypeMethod(tpl, "batch", Database::Batch);
+  Nan::SetPrototypeMethod(tpl, "approximateSize", Database::ApproximateSize);
+  Nan::SetPrototypeMethod(tpl, "getProperty", Database::GetProperty);
+  Nan::SetPrototypeMethod(tpl, "iterator", Database::Iterator);
 }
 
 NAN_METHOD(Database::New) {
-  NanScope();
+  Database* obj = new Database(info[0]);
+  obj->Wrap(info.This());
 
-  NanUtf8String* location = new NanUtf8String(args[0]);
-
-  Database* obj = new Database(location);
-  obj->Wrap(args.This());
-
-  NanReturnValue(args.This());
+  info.GetReturnValue().Set(info.This());
 }
 
-v8::Handle<v8::Value> Database::NewInstance (v8::Local<v8::String> &location) {
-  NanEscapableScope();
+v8::Local<v8::Value> Database::NewInstance (v8::Local<v8::String> &location) {
+  Nan::EscapableHandleScope scope;
 
   v8::Local<v8::Object> instance;
 
   v8::Local<v8::FunctionTemplate> constructorHandle =
-      NanNew<v8::FunctionTemplate>(database_constructor);
+      Nan::New<v8::FunctionTemplate>(database_constructor);
 
-  if (location.IsEmpty()) {
-    instance = constructorHandle->GetFunction()->NewInstance(0, NULL);
-  } else {
-    v8::Handle<v8::Value> argv[] = { location };
-    instance = constructorHandle->GetFunction()->NewInstance(1, argv);
-  }
+  v8::Local<v8::Value> argv[] = { location };
+  instance = constructorHandle->GetFunction()->NewInstance(1, argv);
 
-  return NanEscapeScope(instance);
+  return scope.Escape(instance);
 }
 
 NAN_METHOD(Database::Open) {
-  NanScope();
-
   LD_METHOD_SETUP_COMMON(open, 0, 1)
 
-  bool createIfMissing = NanBooleanOptionValue(
-      optionsObj
-    , NanNew("createIfMissing")
-    , true
-  );
-  bool errorIfExists =
-      NanBooleanOptionValue(optionsObj, NanNew("errorIfExists"));
-  bool compression =
-      NanBooleanOptionValue(optionsObj, NanNew("compression"), true);
+  bool createIfMissing = BooleanOptionValue(optionsObj, "createIfMissing", true);
+  bool errorIfExists = BooleanOptionValue(optionsObj, "errorIfExists");
+  bool compression = BooleanOptionValue(optionsObj, "compression", true);
 
-  uint32_t cacheSize = NanUInt32OptionValue(
-      optionsObj
-    , NanNew("cacheSize")
-    , 8 << 20
-  );
-  uint32_t writeBufferSize = NanUInt32OptionValue(
+  uint32_t cacheSize = UInt32OptionValue(optionsObj, "cacheSize", 8 << 20);
+  uint32_t writeBufferSize = UInt32OptionValue(
       optionsObj
-    , NanNew("writeBufferSize")
+    , "writeBufferSize"
     , 4 << 20
   );
-  uint32_t blockSize = NanUInt32OptionValue(
-      optionsObj
-    , NanNew("blockSize")
-    , 4096
-  );
-  uint32_t maxOpenFiles = NanUInt32OptionValue(
-      optionsObj
-    , NanNew("maxOpenFiles")
-    , 1000
-  );
-  uint32_t blockRestartInterval = NanUInt32OptionValue(
+  uint32_t blockSize = UInt32OptionValue(optionsObj, "blockSize", 4096);
+  uint32_t maxOpenFiles = UInt32OptionValue(optionsObj, "maxOpenFiles", 1000);
+  uint32_t blockRestartInterval = UInt32OptionValue(
       optionsObj
-    , NanNew("blockRestartInterval")
+    , "blockRestartInterval"
     , 16
   );
 
@@ -228,7 +194,7 @@ NAN_METHOD(Database::Open) {
 
   OpenWorker* worker = new OpenWorker(
       database
-    , new NanCallback(callback)
+    , new Nan::Callback(callback)
     , database->blockCache
     , database->filterPolicy
     , createIfMissing
@@ -240,24 +206,24 @@ NAN_METHOD(Database::Open) {
     , blockRestartInterval
   );
   // persist to prevent accidental GC
-  v8::Local<v8::Object> _this = args.This();
+  v8::Local<v8::Object> _this = info.This();
   worker->SaveToPersistent("database", _this);
-  NanAsyncQueueWorker(worker);
+  Nan::AsyncQueueWorker(worker);
+}
 
-  NanReturnUndefined();
+// for an empty callback to iterator.end()
+NAN_METHOD(EmptyMethod) {
 }
 
 NAN_METHOD(Database::Close) {
-  NanScope();
-
   LD_METHOD_SETUP_COMMON_ONEARG(close)
 
   CloseWorker* worker = new CloseWorker(
       database
-    , new NanCallback(callback)
+    , new Nan::Callback(callback)
   );
   // persist to prevent accidental GC
-  v8::Local<v8::Object> _this = args.This();
+  v8::Local<v8::Object> _this = info.This();
   worker->SaveToPersistent("database", _this);
 
   if (!database->iterators.empty()) {
@@ -278,23 +244,17 @@ NAN_METHOD(Database::Close) {
         // function and wait for it to hit ReleaseIterator() where our
         // CloseWorker will be invoked
 
-        /*
-        v8::Local<v8::Object> localHandle = NanNew(it->second);
-        leveldown::Iterator* iterator =
-            node::ObjectWrap::Unwrap<leveldown::Iterator>(localHandle->
-                Get(NanNew("iterator")).As<v8::Object>());
-                */
         leveldown::Iterator *iterator = it->second;
 
         if (!iterator->ended) {
           v8::Local<v8::Function> end =
-              v8::Local<v8::Function>::Cast(NanObjectWrapHandle(iterator)->Get(
-                  NanNew<v8::String>("end")));
+              v8::Local<v8::Function>::Cast(iterator->handle()->Get(
+                  Nan::New<v8::String>("end").ToLocalChecked()));
           v8::Local<v8::Value> argv[] = {
-              NanNew<v8::FunctionTemplate>()->GetFunction() // empty callback
+              Nan::New<v8::FunctionTemplate>(EmptyMethod)->GetFunction() // empty callback
           };
-          NanMakeCallback(
-              NanObjectWrapHandle(iterator)
+          Nan::MakeCallback(
+              iterator->handle()
             , end
             , 1
             , argv
@@ -302,27 +262,23 @@ NAN_METHOD(Database::Close) {
         }
     }
   } else {
-    NanAsyncQueueWorker(worker);
+    Nan::AsyncQueueWorker(worker);
   }
-
-  NanReturnUndefined();
 }
 
 NAN_METHOD(Database::Put) {
-  NanScope();
-
   LD_METHOD_SETUP_COMMON(put, 2, 3)
 
-  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)
+  v8::Local<v8::Object> keyHandle = info[0].As<v8::Object>();
+  v8::Local<v8::Object> valueHandle = info[1].As<v8::Object>();
+  LD_STRING_OR_BUFFER_TO_SLICE(key, keyHandle, key);
+  LD_STRING_OR_BUFFER_TO_SLICE(value, valueHandle, value);
 
-  bool sync = NanBooleanOptionValue(optionsObj, NanNew("sync"));
+  bool sync = BooleanOptionValue(optionsObj, "sync");
 
   WriteWorker* worker  = new WriteWorker(
       database
-    , new NanCallback(callback)
+    , new Nan::Callback(callback)
     , key
     , value
     , sync
@@ -331,81 +287,70 @@ NAN_METHOD(Database::Put) {
   );
 
   // persist to prevent accidental GC
-  v8::Local<v8::Object> _this = args.This();
+  v8::Local<v8::Object> _this = info.This();
   worker->SaveToPersistent("database", _this);
-  NanAsyncQueueWorker(worker);
-
-  NanReturnUndefined();
+  Nan::AsyncQueueWorker(worker);
 }
 
 NAN_METHOD(Database::Get) {
-  NanScope();
-
   LD_METHOD_SETUP_COMMON(get, 1, 2)
 
-  v8::Local<v8::Object> keyHandle = args[0].As<v8::Object>();
-  LD_STRING_OR_BUFFER_TO_SLICE(key, keyHandle, key)
+  v8::Local<v8::Object> keyHandle = info[0].As<v8::Object>();
+  LD_STRING_OR_BUFFER_TO_SLICE(key, keyHandle, key);
 
-  bool asBuffer = NanBooleanOptionValue(optionsObj, NanNew("asBuffer"), true);
-  bool fillCache = NanBooleanOptionValue(optionsObj, NanNew("fillCache"), true);
+  bool asBuffer = BooleanOptionValue(optionsObj, "asBuffer", true);
+  bool fillCache = BooleanOptionValue(optionsObj, "fillCache", true);
 
   ReadWorker* worker = new ReadWorker(
       database
-    , new NanCallback(callback)
+    , new Nan::Callback(callback)
     , key
     , asBuffer
     , fillCache
     , keyHandle
   );
   // persist to prevent accidental GC
-  v8::Local<v8::Object> _this = args.This();
+  v8::Local<v8::Object> _this = info.This();
   worker->SaveToPersistent("database", _this);
-  NanAsyncQueueWorker(worker);
-
-  NanReturnUndefined();
+  Nan::AsyncQueueWorker(worker);
 }
 
 NAN_METHOD(Database::Delete) {
-  NanScope();
-
   LD_METHOD_SETUP_COMMON(del, 1, 2)
 
-  v8::Local<v8::Object> keyHandle = args[0].As<v8::Object>();
-  LD_STRING_OR_BUFFER_TO_SLICE(key, keyHandle, key)
+  v8::Local<v8::Object> keyHandle = info[0].As<v8::Object>();
+  LD_STRING_OR_BUFFER_TO_SLICE(key, keyHandle, key);
 
-  bool sync = NanBooleanOptionValue(optionsObj, NanNew("sync"));
+  bool sync = BooleanOptionValue(optionsObj, "sync");
 
   DeleteWorker* worker = new DeleteWorker(
       database
-    , new NanCallback(callback)
+    , new Nan::Callback(callback)
     , key
     , sync
     , keyHandle
   );
   // persist to prevent accidental GC
-  v8::Local<v8::Object> _this = args.This();
+  v8::Local<v8::Object> _this = info.This();
   worker->SaveToPersistent("database", _this);
-  NanAsyncQueueWorker(worker);
-
-  NanReturnUndefined();
+  Nan::AsyncQueueWorker(worker);
 }
 
 NAN_METHOD(Database::Batch) {
-  NanScope();
-
-  if ((args.Length() == 0 || args.Length() == 1) && !args[0]->IsArray()) {
+  if ((info.Length() == 0 || info.Length() == 1) && !info[0]->IsArray()) {
     v8::Local<v8::Object> optionsObj;
-    if (args.Length() > 0 && args[0]->IsObject()) {
-      optionsObj = args[0].As<v8::Object>();
+    if (info.Length() > 0 && info[0]->IsObject()) {
+      optionsObj = info[0].As<v8::Object>();
     }
-    NanReturnValue(Batch::NewInstance(args.This(), optionsObj));
+    info.GetReturnValue().Set(Batch::NewInstance(info.This(), optionsObj));
+    return;
   }
 
-  LD_METHOD_SETUP_COMMON(batch, 1, 2)
+  LD_METHOD_SETUP_COMMON(batch, 1, 2);
 
-  bool sync = NanBooleanOptionValue(optionsObj, NanNew("sync"));
+  bool sync = BooleanOptionValue(optionsObj, "sync");
 
-  v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[0]);
+  v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(info[0]);
 
   leveldb::WriteBatch* batch = new leveldb::WriteBatch();
   bool hasData = false;
@@ -415,10 +360,10 @@ NAN_METHOD(Database::Batch) {
       continue;
 
     v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(array->Get(i));
-    v8::Local<v8::Value> keyBuffer = obj->Get(NanNew("key"));
-    v8::Local<v8::Value> type = obj->Get(NanNew("type"));
+    v8::Local<v8::Value> keyBuffer = obj->Get(Nan::New("key").ToLocalChecked());
+    v8::Local<v8::Value> type = obj->Get(Nan::New("type").ToLocalChecked());
 
-    if (type->StrictEquals(NanNew("del"))) {
+    if (type->StrictEquals(Nan::New("del").ToLocalChecked())) {
       LD_STRING_OR_BUFFER_TO_SLICE(key, keyBuffer, key)
 
       batch->Delete(key);
@@ -426,8 +371,8 @@ NAN_METHOD(Database::Batch) {
         hasData = true;
 
       DisposeStringOrBufferFromSlice(keyBuffer, key);
-    } else if (type->StrictEquals(NanNew("put"))) {
-      v8::Local<v8::Value> valueBuffer = obj->Get(NanNew("value"));
+    } else if (type->StrictEquals(Nan::New("put").ToLocalChecked())) {
+      v8::Local<v8::Value> valueBuffer = obj->Get(Nan::New("value").ToLocalChecked());
 
       LD_STRING_OR_BUFFER_TO_SLICE(key, keyBuffer, key)
       LD_STRING_OR_BUFFER_TO_SLICE(value, valueBuffer, value)
@@ -444,26 +389,22 @@ NAN_METHOD(Database::Batch) {
   if (hasData) {
     BatchWorker* worker = new BatchWorker(
         database
-      , new NanCallback(callback)
+      , new Nan::Callback(callback)
       , batch
       , sync
     );
     // persist to prevent accidental GC
-    v8::Local<v8::Object> _this = args.This();
+    v8::Local<v8::Object> _this = info.This();
     worker->SaveToPersistent("database", _this);
-    NanAsyncQueueWorker(worker);
+    Nan::AsyncQueueWorker(worker);
   } else {
     LD_RUN_CALLBACK(callback, 0, NULL);
   }
-
-  NanReturnUndefined();
 }
 
 NAN_METHOD(Database::ApproximateSize) {
-  NanScope();
-
-  v8::Local<v8::Object> startHandle = args[0].As<v8::Object>();
-  v8::Local<v8::Object> endHandle = args[1].As<v8::Object>();
+  v8::Local<v8::Object> startHandle = info[0].As<v8::Object>();
+  v8::Local<v8::Object> endHandle = info[1].As<v8::Object>();
 
   LD_METHOD_SETUP_COMMON(approximateSize, -1, 2)
 
@@ -472,49 +413,43 @@ NAN_METHOD(Database::ApproximateSize) {
 
   ApproximateSizeWorker* worker  = new ApproximateSizeWorker(
       database
-    , new NanCallback(callback)
+    , new Nan::Callback(callback)
     , start
     , end
     , startHandle
     , endHandle
   );
   // persist to prevent accidental GC
-  v8::Local<v8::Object> _this = args.This();
+  v8::Local<v8::Object> _this = info.This();
   worker->SaveToPersistent("database", _this);
-  NanAsyncQueueWorker(worker);
-
-  NanReturnUndefined();
+  Nan::AsyncQueueWorker(worker);
 }
 
 NAN_METHOD(Database::GetProperty) {
-  NanScope();
-
-  v8::Local<v8::Value> propertyHandle = args[0].As<v8::Object>();
+  v8::Local<v8::Value> propertyHandle = info[0].As<v8::Object>();
   v8::Local<v8::Function> callback; // for LD_STRING_OR_BUFFER_TO_SLICE
 
   LD_STRING_OR_BUFFER_TO_SLICE(property, propertyHandle, property)
 
   leveldown::Database* database =
-      node::ObjectWrap::Unwrap<leveldown::Database>(args.This());
+      Nan::ObjectWrap::Unwrap<leveldown::Database>(info.This());
 
   std::string* value = new std::string();
   database->GetPropertyFromDatabase(property, value);
   v8::Local<v8::String> returnValue
-      = NanNew<v8::String>(value->c_str(), value->length());
+      = Nan::New<v8::String>(value->c_str(), value->length()).ToLocalChecked();
   delete value;
   delete[] property.data();
 
-  NanReturnValue(returnValue);
+  info.GetReturnValue().Set(returnValue);
 }
 
 NAN_METHOD(Database::Iterator) {
-  NanScope();
-
-  Database* database = node::ObjectWrap::Unwrap<Database>(args.This());
+  Database* database = Nan::ObjectWrap::Unwrap<Database>(info.This());
 
   v8::Local<v8::Object> optionsObj;
-  if (args.Length() > 0 && args[0]->IsObject()) {
-    optionsObj = v8::Local<v8::Object>::Cast(args[0]);
+  if (info.Length() > 0 && info[0]->IsObject()) {
+    optionsObj = v8::Local<v8::Object>::Cast(info[0]);
   }
 
   // each iterator gets a unique id for this Database, so we can
@@ -522,31 +457,31 @@ NAN_METHOD(Database::Iterator) {
   uint32_t id = database->currentIteratorId++;
   v8::TryCatch try_catch;
   v8::Local<v8::Object> iteratorHandle = Iterator::NewInstance(
-      args.This()
-    , NanNew<v8::Number>(id)
+      info.This()
+    , Nan::New<v8::Number>(id)
     , optionsObj
   );
   if (try_catch.HasCaught()) {
     // NB: node::FatalException can segfault here if there is no room on stack.
-    return NanThrowError("Fatal Error in Database::Iterator!");
+    return Nan::ThrowError("Fatal Error in Database::Iterator!");
   }
 
   leveldown::Iterator *iterator =
-      node::ObjectWrap::Unwrap<leveldown::Iterator>(iteratorHandle);
+      Nan::ObjectWrap::Unwrap<leveldown::Iterator>(iteratorHandle);
 
   database->iterators[id] = iterator;
 
   // register our iterator
   /*
-  v8::Local<v8::Object> obj = NanNew<v8::Object>();
-  obj->Set(NanNew("iterator"), iteratorHandle);
-  v8::Persistent<v8::Object> persistent;
+  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
+  obj->Set(Nan::New("iterator"), iteratorHandle);
+  Nan::Persistent<v8::Object> persistent;
   persistent.Reset(nan_isolate, obj);
-  database->iterators.insert(std::pair< uint32_t, v8::Persistent<v8::Object> & >
+  database->iterators.insert(std::pair< uint32_t, Nan::Persistent<v8::Object> & >
       (id, persistent));
   */
 
-  NanReturnValue(iteratorHandle);
+  info.GetReturnValue().Set(iteratorHandle);
 }
 
 
diff --git a/src/database.h b/src/database.h
index 2517d09..dd833ee 100644
--- a/src/database.h
+++ b/src/database.h
@@ -23,13 +23,13 @@ namespace leveldown {
 NAN_METHOD(LevelDOWN);
 
 struct Reference {
-  v8::Persistent<v8::Object> handle;
+  Nan::Persistent<v8::Object> handle;
   leveldb::Slice slice;
 
   Reference(v8::Local<v8::Value> obj, leveldb::Slice slice) : slice(slice) {
-    v8::Local<v8::Object> _obj = NanNew<v8::Object>();
-    _obj->Set(NanNew("obj"), obj);
-    NanAssignPersistent(handle, _obj);
+    v8::Local<v8::Object> _obj = Nan::New<v8::Object>();
+    _obj->Set(Nan::New("obj").ToLocalChecked(), obj);
+    handle.Reset(_obj);
   };
 };
 
@@ -43,12 +43,12 @@ static inline void ClearReferences (std::vector<Reference *> *references) {
   delete references;
 }
 
-class Database : public node::ObjectWrap {
+class Database : public Nan::ObjectWrap {
 public:
   static void Init ();
-  static v8::Handle<v8::Value> NewInstance (v8::Local<v8::String> &location);
+  static v8::Local<v8::Value> NewInstance (v8::Local<v8::String> &location);
 
-  leveldb::Status OpenDatabase (leveldb::Options* options, std::string location);
+  leveldb::Status OpenDatabase (leveldb::Options* options);
   leveldb::Status PutToDatabase (
       leveldb::WriteOptions* options
     , leveldb::Slice key
@@ -73,19 +73,18 @@ public:
   const leveldb::Snapshot* NewSnapshot ();
   void ReleaseSnapshot (const leveldb::Snapshot* snapshot);
   void CloseDatabase ();
-  NanUtf8String* Location();
   void ReleaseIterator (uint32_t id);
 
-  Database (NanUtf8String* location);
+  Database (const v8::Local<v8::Value>& from);
   ~Database ();
 
 private:
+  Nan::Utf8String* location;
   leveldb::DB* db;
-  const leveldb::FilterPolicy* filterPolicy;
-  leveldb::Cache* blockCache;
-  NanUtf8String* location;
   uint32_t currentIteratorId;
   void(*pendingCloseWorker);
+  leveldb::Cache* blockCache;
+  const leveldb::FilterPolicy* filterPolicy;
 
   std::map< uint32_t, leveldown::Iterator * > iterators;
 
diff --git a/src/database_async.cc b/src/database_async.cc
index 5ed674e..b5533bd 100644
--- a/src/database_async.cc
+++ b/src/database_async.cc
@@ -20,7 +20,7 @@ namespace leveldown {
 
 OpenWorker::OpenWorker (
     Database *database
-  , NanCallback *callback
+  , Nan::Callback *callback
   , leveldb::Cache* blockCache
   , const leveldb::FilterPolicy* filterPolicy
   , bool createIfMissing
@@ -51,14 +51,14 @@ OpenWorker::~OpenWorker () {
 }
 
 void OpenWorker::Execute () {
-  SetStatus(database->OpenDatabase(options, **(database->Location())));
+  SetStatus(database->OpenDatabase(options));
 }
 
 /** CLOSE WORKER **/
 
 CloseWorker::CloseWorker (
     Database *database
-  , NanCallback *callback
+  , Nan::Callback *callback
 ) : AsyncWorker(database, callback)
 {};
 
@@ -69,7 +69,7 @@ void CloseWorker::Execute () {
 }
 
 void CloseWorker::WorkComplete () {
-  NanScope();
+  Nan::HandleScope scope;
   HandleOKCallback();
   delete callback;
   callback = NULL;
@@ -79,13 +79,13 @@ void CloseWorker::WorkComplete () {
 
 IOWorker::IOWorker (
     Database *database
-  , NanCallback *callback
+  , Nan::Callback *callback
   , leveldb::Slice key
   , v8::Local<v8::Object> &keyHandle
 ) : AsyncWorker(database, callback)
   , key(key)
 {
-  NanScope();
+  Nan::HandleScope scope;
 
   SaveToPersistent("key", keyHandle);
 };
@@ -93,7 +93,7 @@ IOWorker::IOWorker (
 IOWorker::~IOWorker () {}
 
 void IOWorker::WorkComplete () {
-  NanScope();
+  Nan::HandleScope scope;
 
   DisposeStringOrBufferFromSlice(GetFromPersistent("key"), key);
   AsyncWorker::WorkComplete();
@@ -103,7 +103,7 @@ void IOWorker::WorkComplete () {
 
 ReadWorker::ReadWorker (
     Database *database
-  , NanCallback *callback
+  , Nan::Callback *callback
   , leveldb::Slice key
   , bool asBuffer
   , bool fillCache
@@ -111,7 +111,7 @@ ReadWorker::ReadWorker (
 ) : IOWorker(database, callback, key, keyHandle)
   , asBuffer(asBuffer)
 {
-  NanScope();
+  Nan::HandleScope scope;
 
   options = new leveldb::ReadOptions();
   options->fill_cache = fillCache;
@@ -127,16 +127,19 @@ void ReadWorker::Execute () {
 }
 
 void ReadWorker::HandleOKCallback () {
-  NanScope();
+  Nan::HandleScope scope;
 
   v8::Local<v8::Value> returnValue;
   if (asBuffer) {
-    returnValue = NanNewBufferHandle((char*)value.data(), value.size());
+    //TODO: could use NewBuffer if we carefully manage the lifecycle of `value`
+    //and avoid an an extra allocation. We'd have to clean up properly when not OK
+    //and let the new Buffer manage the data when OK
+    returnValue = Nan::CopyBuffer((char*)value.data(), value.size()).ToLocalChecked();
   } else {
-    returnValue = NanNew<v8::String>((char*)value.data(), value.size());
+    returnValue = Nan::New<v8::String>((char*)value.data(), value.size()).ToLocalChecked();
   }
   v8::Local<v8::Value> argv[] = {
-      NanNull()
+      Nan::Null()
     , returnValue
   };
   callback->Call(2, argv);
@@ -146,13 +149,13 @@ void ReadWorker::HandleOKCallback () {
 
 DeleteWorker::DeleteWorker (
     Database *database
-  , NanCallback *callback
+  , Nan::Callback *callback
   , leveldb::Slice key
   , bool sync
   , v8::Local<v8::Object> &keyHandle
 ) : IOWorker(database, callback, key, keyHandle)
 {
-  NanScope();
+  Nan::HandleScope scope;
 
   options = new leveldb::WriteOptions();
   options->sync = sync;
@@ -171,7 +174,7 @@ void DeleteWorker::Execute () {
 
 WriteWorker::WriteWorker (
     Database *database
-  , NanCallback *callback
+  , Nan::Callback *callback
   , leveldb::Slice key
   , leveldb::Slice value
   , bool sync
@@ -180,7 +183,7 @@ WriteWorker::WriteWorker (
 ) : DeleteWorker(database, callback, key, sync, keyHandle)
   , value(value)
 {
-  NanScope();
+  Nan::HandleScope scope;
 
   SaveToPersistent("value", valueHandle);
 };
@@ -192,7 +195,7 @@ void WriteWorker::Execute () {
 }
 
 void WriteWorker::WorkComplete () {
-  NanScope();
+  Nan::HandleScope scope;
 
   DisposeStringOrBufferFromSlice(GetFromPersistent("value"), value);
   IOWorker::WorkComplete();
@@ -202,7 +205,7 @@ void WriteWorker::WorkComplete () {
 
 BatchWorker::BatchWorker (
     Database *database
-  , NanCallback *callback
+  , Nan::Callback *callback
   , leveldb::WriteBatch* batch
   , bool sync
 ) : AsyncWorker(database, callback)
@@ -225,7 +228,7 @@ void BatchWorker::Execute () {
 
 ApproximateSizeWorker::ApproximateSizeWorker (
     Database *database
-  , NanCallback *callback
+  , Nan::Callback *callback
   , leveldb::Slice start
   , leveldb::Slice end
   , v8::Local<v8::Object> &startHandle
@@ -233,7 +236,7 @@ ApproximateSizeWorker::ApproximateSizeWorker (
 ) : AsyncWorker(database, callback)
   , range(start, end)
 {
-  NanScope();
+  Nan::HandleScope scope;
 
   SaveToPersistent("start", startHandle);
   SaveToPersistent("end", endHandle);
@@ -246,7 +249,7 @@ void ApproximateSizeWorker::Execute () {
 }
 
 void ApproximateSizeWorker::WorkComplete() {
-  NanScope();
+  Nan::HandleScope scope;
 
   DisposeStringOrBufferFromSlice(GetFromPersistent("start"), range.start);
   DisposeStringOrBufferFromSlice(GetFromPersistent("end"), range.limit);
@@ -254,11 +257,11 @@ void ApproximateSizeWorker::WorkComplete() {
 }
 
 void ApproximateSizeWorker::HandleOKCallback () {
-  NanScope();
+  Nan::HandleScope scope;
 
-  v8::Local<v8::Value> returnValue = NanNew<v8::Number>((double) size);
+  v8::Local<v8::Value> returnValue = Nan::New<v8::Number>((double) size);
   v8::Local<v8::Value> argv[] = {
-      NanNull()
+      Nan::Null()
     , returnValue
   };
   callback->Call(2, argv);
diff --git a/src/database_async.h b/src/database_async.h
index 60b7d1b..e0a8f80 100644
--- a/src/database_async.h
+++ b/src/database_async.h
@@ -19,7 +19,7 @@ class OpenWorker : public AsyncWorker {
 public:
   OpenWorker (
       Database *database
-    , NanCallback *callback
+    , Nan::Callback *callback
     , leveldb::Cache* blockCache
     , const leveldb::FilterPolicy* filterPolicy
     , bool createIfMissing
@@ -42,7 +42,7 @@ class CloseWorker : public AsyncWorker {
 public:
   CloseWorker (
       Database *database
-    , NanCallback *callback
+    , Nan::Callback *callback
   );
 
   virtual ~CloseWorker ();
@@ -54,7 +54,7 @@ class IOWorker    : public AsyncWorker {
 public:
   IOWorker (
       Database *database
-    , NanCallback *callback
+    , Nan::Callback *callback
     , leveldb::Slice key
     , v8::Local<v8::Object> &keyHandle
   );
@@ -70,7 +70,7 @@ class ReadWorker : public IOWorker {
 public:
   ReadWorker (
       Database *database
-    , NanCallback *callback
+    , Nan::Callback *callback
     , leveldb::Slice key
     , bool asBuffer
     , bool fillCache
@@ -91,7 +91,7 @@ class DeleteWorker : public IOWorker {
 public:
   DeleteWorker (
       Database *database
-    , NanCallback *callback
+    , Nan::Callback *callback
     , leveldb::Slice key
     , bool sync
     , v8::Local<v8::Object> &keyHandle
@@ -108,7 +108,7 @@ class WriteWorker : public DeleteWorker {
 public:
   WriteWorker (
       Database *database
-    , NanCallback *callback
+    , Nan::Callback *callback
     , leveldb::Slice key
     , leveldb::Slice value
     , bool sync
@@ -128,7 +128,7 @@ class BatchWorker : public AsyncWorker {
 public:
   BatchWorker (
       Database *database
-    , NanCallback *callback
+    , Nan::Callback *callback
     , leveldb::WriteBatch* batch
     , bool sync
   );
@@ -145,7 +145,7 @@ class ApproximateSizeWorker : public AsyncWorker {
 public:
   ApproximateSizeWorker (
       Database *database
-    , NanCallback *callback
+    , Nan::Callback *callback
     , leveldb::Slice start
     , leveldb::Slice end
     , v8::Local<v8::Object> &startHandle
diff --git a/src/iterator.cc b/src/iterator.cc
index 005c274..37c5ede 100644
--- a/src/iterator.cc
+++ b/src/iterator.cc
@@ -9,10 +9,11 @@
 #include "database.h"
 #include "iterator.h"
 #include "iterator_async.h"
+#include "common.h"
 
 namespace leveldown {
 
-static v8::Persistent<v8::FunctionTemplate> iterator_constructor;
+static Nan::Persistent<v8::FunctionTemplate> iterator_constructor;
 
 Iterator::Iterator (
     Database* database
@@ -48,12 +49,12 @@ Iterator::Iterator (
   , keyAsBuffer(keyAsBuffer)
   , valueAsBuffer(valueAsBuffer)
 {
-  NanScope();
+  Nan::HandleScope scope;
 
-  v8::Local<v8::Object> obj = NanNew<v8::Object>();
+  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
   if (!startHandle.IsEmpty())
-    obj->Set(NanNew("start"), startHandle);
-  NanAssignPersistent(persistentHandle, obj);
+    obj->Set(Nan::New("start").ToLocalChecked(), startHandle);
+  persistentHandle.Reset(obj);
 
   options    = new leveldb::ReadOptions();
   options->fill_cache = fillCache;
@@ -61,6 +62,7 @@ Iterator::Iterator (
   options->snapshot = database->NewSnapshot();
   dbIterator = NULL;
   count      = 0;
+  seeking    = false;
   nexting    = false;
   ended      = false;
   endWorker  = NULL;
@@ -69,7 +71,7 @@ Iterator::Iterator (
 Iterator::~Iterator () {
   delete options;
   if (!persistentHandle.IsEmpty())
-    NanDisposePersistent(persistentHandle);
+    persistentHandle.Reset();
   if (start != NULL)
     delete start;
   if (end != NULL)
@@ -124,13 +126,15 @@ bool Iterator::GetIterator () {
 
 bool Iterator::Read (std::string& key, std::string& value) {
   // if it's not the first call, move to next item.
-  if (!GetIterator()) {
+  if (!GetIterator() && !seeking) {
     if (reverse)
       dbIterator->Prev();
     else
       dbIterator->Next();
   }
 
+  seeking = false;
+
   // now check if this is the end or not, if not then return the key & value
   if (dbIterator->Valid()) {
     std::string key_ = dbIterator->key().ToString();
@@ -194,66 +198,110 @@ void Iterator::Release () {
 void checkEndCallback (Iterator* iterator) {
   iterator->nexting = false;
   if (iterator->endWorker != NULL) {
-    NanAsyncQueueWorker(iterator->endWorker);
+    Nan::AsyncQueueWorker(iterator->endWorker);
     iterator->endWorker = NULL;
   }
 }
 
+NAN_METHOD(Iterator::Seek) {
+  Iterator* iterator = Nan::ObjectWrap::Unwrap<Iterator>(info.This());
+  iterator->GetIterator();
+  leveldb::Iterator* dbIterator = iterator->dbIterator;
+  Nan::Utf8String key(info[0]);
+
+  dbIterator->Seek(*key);
+  iterator->seeking = true;
+
+  if (dbIterator->Valid()) {
+    int cmp = dbIterator->key().compare(*key);
+    if (cmp > 0 && iterator->reverse) {
+      dbIterator->Prev();
+    } else if (cmp < 0 && !iterator->reverse) {
+      dbIterator->Next();
+    }
+  } else {
+    if (iterator->reverse) {
+      dbIterator->SeekToLast();
+    } else {
+      dbIterator->SeekToFirst();
+    }
+    if (dbIterator->Valid()) {
+      int cmp = dbIterator->key().compare(*key);
+      if (cmp > 0 && iterator->reverse) {
+        dbIterator->SeekToFirst();
+        dbIterator->Prev();
+      } else if (cmp < 0 && !iterator->reverse) {
+        dbIterator->SeekToLast();
+        dbIterator->Next();
+      }
+    }
+  }
+
+  info.GetReturnValue().Set(info.Holder());
+}
+
 NAN_METHOD(Iterator::Next) {
-  NanScope();
+  Iterator* iterator = Nan::ObjectWrap::Unwrap<Iterator>(info.This());
 
-  Iterator* iterator = node::ObjectWrap::Unwrap<Iterator>(args.This());
+  if (!info[0]->IsFunction()) {
+    return Nan::ThrowError("next() requires a callback argument");
+  }
 
-  v8::Local<v8::Function> callback = args[0].As<v8::Function>();
+  v8::Local<v8::Function> callback = info[0].As<v8::Function>();
 
   NextWorker* worker = new NextWorker(
       iterator
-    , new NanCallback(callback)
+    , new Nan::Callback(callback)
     , checkEndCallback
   );
   // persist to prevent accidental GC
-  v8::Local<v8::Object> _this = args.This();
+  v8::Local<v8::Object> _this = info.This();
   worker->SaveToPersistent("iterator", _this);
   iterator->nexting = true;
-  NanAsyncQueueWorker(worker);
+  Nan::AsyncQueueWorker(worker);
 
-  NanReturnValue(args.Holder());
+  info.GetReturnValue().Set(info.Holder());
 }
 
 NAN_METHOD(Iterator::End) {
-  NanScope();
-
-  Iterator* iterator = node::ObjectWrap::Unwrap<Iterator>(args.This());
+  Iterator* iterator = Nan::ObjectWrap::Unwrap<Iterator>(info.This());
 
-  v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[0]);
-
-  EndWorker* worker = new EndWorker(
-      iterator
-    , new NanCallback(callback)
-  );
-  // persist to prevent accidental GC
-  v8::Local<v8::Object> _this = args.This();
-  worker->SaveToPersistent("iterator", _this);
-  iterator->ended = true;
+  if (!info[0]->IsFunction()) {
+    return Nan::ThrowError("end() requires a callback argument");
+  }
 
-  if (iterator->nexting) {
-    // waiting for a next() to return, queue the end
-    iterator->endWorker = worker;
-  } else {
-    NanAsyncQueueWorker(worker);
+  if (!iterator->ended) {
+    v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(info[0]);
+
+    EndWorker* worker = new EndWorker(
+        iterator
+      , new Nan::Callback(callback)
+    );
+    // persist to prevent accidental GC
+    v8::Local<v8::Object> _this = info.This();
+    worker->SaveToPersistent("iterator", _this);
+    iterator->ended = true;
+
+    if (iterator->nexting) {
+      // waiting for a next() to return, queue the end
+      iterator->endWorker = worker;
+    } else {
+      Nan::AsyncQueueWorker(worker);
+    }
   }
 
-  NanReturnValue(args.Holder());
+  info.GetReturnValue().Set(info.Holder());
 }
 
 void Iterator::Init () {
   v8::Local<v8::FunctionTemplate> tpl =
-      NanNew<v8::FunctionTemplate>(Iterator::New);
-  NanAssignPersistent(iterator_constructor, tpl);
-  tpl->SetClassName(NanNew("Iterator"));
+      Nan::New<v8::FunctionTemplate>(Iterator::New);
+  iterator_constructor.Reset(tpl);
+  tpl->SetClassName(Nan::New("Iterator").ToLocalChecked());
   tpl->InstanceTemplate()->SetInternalFieldCount(1);
-  NODE_SET_PROTOTYPE_METHOD(tpl, "next", Iterator::Next);
-  NODE_SET_PROTOTYPE_METHOD(tpl, "end", Iterator::End);
+  Nan::SetPrototypeMethod(tpl, "seek", Iterator::Seek);
+  Nan::SetPrototypeMethod(tpl, "next", Iterator::Next);
+  Nan::SetPrototypeMethod(tpl, "end", Iterator::End);
 }
 
 v8::Local<v8::Object> Iterator::NewInstance (
@@ -262,30 +310,28 @@ v8::Local<v8::Object> Iterator::NewInstance (
       , v8::Local<v8::Object> optionsObj
     ) {
 
-  NanEscapableScope();
+  Nan::EscapableHandleScope scope;
 
   v8::Local<v8::Object> instance;
   v8::Local<v8::FunctionTemplate> constructorHandle =
-      NanNew<v8::FunctionTemplate>(iterator_constructor);
+      Nan::New<v8::FunctionTemplate>(iterator_constructor);
 
   if (optionsObj.IsEmpty()) {
-    v8::Handle<v8::Value> argv[2] = { database, id };
+    v8::Local<v8::Value> argv[2] = { database, id };
     instance = constructorHandle->GetFunction()->NewInstance(2, argv);
   } else {
-    v8::Handle<v8::Value> argv[3] = { database, id, optionsObj };
+    v8::Local<v8::Value> argv[3] = { database, id, optionsObj };
     instance = constructorHandle->GetFunction()->NewInstance(3, argv);
   }
 
-  return NanEscapeScope(instance);
+  return scope.Escape(instance);
 }
 
 NAN_METHOD(Iterator::New) {
-  NanScope();
-
-  Database* database = node::ObjectWrap::Unwrap<Database>(args[0]->ToObject());
+  Database* database = Nan::ObjectWrap::Unwrap<Database>(info[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::Function> callback;
 
   v8::Local<v8::Object> startHandle;
   leveldb::Slice* start = NULL;
@@ -294,7 +340,7 @@ NAN_METHOD(Iterator::New) {
   // default highWaterMark from Readble-streams
   size_t highWaterMark = 16 * 1024;
 
-  v8::Local<v8::Value> id = args[1];
+  v8::Local<v8::Value> id = info[1];
 
   v8::Local<v8::Object> optionsObj;
 
@@ -311,16 +357,16 @@ NAN_METHOD(Iterator::New) {
   //default to forward.
   bool reverse = false;
 
-  if (args.Length() > 1 && args[2]->IsObject()) {
-    optionsObj = v8::Local<v8::Object>::Cast(args[2]);
+  if (info.Length() > 1 && info[2]->IsObject()) {
+    optionsObj = v8::Local<v8::Object>::Cast(info[2]);
 
-    reverse = NanBooleanOptionValue(optionsObj, NanNew("reverse"));
+    reverse = BooleanOptionValue(optionsObj, "reverse");
 
-    if (optionsObj->Has(NanNew("start"))
-        && (node::Buffer::HasInstance(optionsObj->Get(NanNew("start")))
-          || optionsObj->Get(NanNew("start"))->IsString())) {
+    if (optionsObj->Has(Nan::New("start").ToLocalChecked())
+        && (node::Buffer::HasInstance(optionsObj->Get(Nan::New("start").ToLocalChecked()))
+          || optionsObj->Get(Nan::New("start").ToLocalChecked())->IsString())) {
 
-      startHandle = optionsObj->Get(NanNew("start")).As<v8::Object>();
+      startHandle = optionsObj->Get(Nan::New("start").ToLocalChecked()).As<v8::Object>();
 
       // ignore start if it has size 0 since a Slice can't have length 0
       if (StringOrBufferLength(startHandle) > 0) {
@@ -329,11 +375,11 @@ NAN_METHOD(Iterator::New) {
       }
     }
 
-    if (optionsObj->Has(NanNew("end"))
-        && (node::Buffer::HasInstance(optionsObj->Get(NanNew("end")))
-          || optionsObj->Get(NanNew("end"))->IsString())) {
+    if (optionsObj->Has(Nan::New("end").ToLocalChecked())
+        && (node::Buffer::HasInstance(optionsObj->Get(Nan::New("end").ToLocalChecked()))
+          || optionsObj->Get(Nan::New("end").ToLocalChecked())->IsString())) {
 
-      v8::Local<v8::Value> endBuffer = optionsObj->Get(NanNew("end"));
+      v8::Local<v8::Value> endBuffer = optionsObj->Get(Nan::New("end").ToLocalChecked());
 
       // ignore end if it has size 0 since a Slice can't have length 0
       if (StringOrBufferLength(endBuffer) > 0) {
@@ -342,21 +388,21 @@ NAN_METHOD(Iterator::New) {
       }
     }
 
-    if (!optionsObj.IsEmpty() && optionsObj->Has(NanNew("limit"))) {
+    if (!optionsObj.IsEmpty() && optionsObj->Has(Nan::New("limit").ToLocalChecked())) {
       limit = v8::Local<v8::Integer>::Cast(optionsObj->Get(
-          NanNew("limit")))->Value();
+          Nan::New("limit").ToLocalChecked()))->Value();
     }
 
-    if (optionsObj->Has(NanNew("highWaterMark"))) {
+    if (optionsObj->Has(Nan::New("highWaterMark").ToLocalChecked())) {
       highWaterMark = v8::Local<v8::Integer>::Cast(optionsObj->Get(
-            NanNew("highWaterMark")))->Value();
+            Nan::New("highWaterMark").ToLocalChecked()))->Value();
     }
 
-    if (optionsObj->Has(NanNew("lt"))
-        && (node::Buffer::HasInstance(optionsObj->Get(NanNew("lt")))
-          || optionsObj->Get(NanNew("lt"))->IsString())) {
+    if (optionsObj->Has(Nan::New("lt").ToLocalChecked())
+        && (node::Buffer::HasInstance(optionsObj->Get(Nan::New("lt").ToLocalChecked()))
+          || optionsObj->Get(Nan::New("lt").ToLocalChecked())->IsString())) {
 
-      v8::Local<v8::Value> ltBuffer = optionsObj->Get(NanNew("lt"));
+      v8::Local<v8::Value> ltBuffer = optionsObj->Get(Nan::New("lt").ToLocalChecked());
 
       // ignore end if it has size 0 since a Slice can't have length 0
       if (StringOrBufferLength(ltBuffer) > 0) {
@@ -367,11 +413,11 @@ NAN_METHOD(Iterator::New) {
       }
     }
 
-    if (optionsObj->Has(NanNew("lte"))
-        && (node::Buffer::HasInstance(optionsObj->Get(NanNew("lte")))
-          || optionsObj->Get(NanNew("lte"))->IsString())) {
+    if (optionsObj->Has(Nan::New("lte").ToLocalChecked())
+        && (node::Buffer::HasInstance(optionsObj->Get(Nan::New("lte").ToLocalChecked()))
+          || optionsObj->Get(Nan::New("lte").ToLocalChecked())->IsString())) {
 
-      v8::Local<v8::Value> lteBuffer = optionsObj->Get(NanNew("lte"));
+      v8::Local<v8::Value> lteBuffer = optionsObj->Get(Nan::New("lte").ToLocalChecked());
 
       // ignore end if it has size 0 since a Slice can't have length 0
       if (StringOrBufferLength(lteBuffer) > 0) {
@@ -382,11 +428,11 @@ NAN_METHOD(Iterator::New) {
       }
     }
 
-    if (optionsObj->Has(NanNew("gt"))
-        && (node::Buffer::HasInstance(optionsObj->Get(NanNew("gt")))
-          || optionsObj->Get(NanNew("gt"))->IsString())) {
+    if (optionsObj->Has(Nan::New("gt").ToLocalChecked())
+        && (node::Buffer::HasInstance(optionsObj->Get(Nan::New("gt").ToLocalChecked()))
+          || optionsObj->Get(Nan::New("gt").ToLocalChecked())->IsString())) {
 
-      v8::Local<v8::Value> gtBuffer = optionsObj->Get(NanNew("gt"));
+      v8::Local<v8::Value> gtBuffer = optionsObj->Get(Nan::New("gt").ToLocalChecked());
 
       // ignore end if it has size 0 since a Slice can't have length 0
       if (StringOrBufferLength(gtBuffer) > 0) {
@@ -397,11 +443,11 @@ NAN_METHOD(Iterator::New) {
       }
     }
 
-    if (optionsObj->Has(NanNew("gte"))
-        && (node::Buffer::HasInstance(optionsObj->Get(NanNew("gte")))
-          || optionsObj->Get(NanNew("gte"))->IsString())) {
+    if (optionsObj->Has(Nan::New("gte").ToLocalChecked())
+        && (node::Buffer::HasInstance(optionsObj->Get(Nan::New("gte").ToLocalChecked()))
+          || optionsObj->Get(Nan::New("gte").ToLocalChecked())->IsString())) {
 
-      v8::Local<v8::Value> gteBuffer = optionsObj->Get(NanNew("gte"));
+      v8::Local<v8::Value> gteBuffer = optionsObj->Get(Nan::New("gte").ToLocalChecked());
 
       // ignore end if it has size 0 since a Slice can't have length 0
       if (StringOrBufferLength(gteBuffer) > 0) {
@@ -414,19 +460,11 @@ NAN_METHOD(Iterator::New) {
 
   }
 
-  bool keys = NanBooleanOptionValue(optionsObj, NanNew("keys"), true);
-  bool values = NanBooleanOptionValue(optionsObj, NanNew("values"), true);
-  bool keyAsBuffer = NanBooleanOptionValue(
-      optionsObj
-    , NanNew("keyAsBuffer")
-    , true
-  );
-  bool valueAsBuffer = NanBooleanOptionValue(
-      optionsObj
-    , NanNew("valueAsBuffer")
-    , true
-  );
-  bool fillCache = NanBooleanOptionValue(optionsObj, NanNew("fillCache"));
+  bool keys = BooleanOptionValue(optionsObj, "keys", true);
+  bool values = BooleanOptionValue(optionsObj, "values", true);
+  bool keyAsBuffer = BooleanOptionValue(optionsObj, "keyAsBuffer", true);
+  bool valueAsBuffer = BooleanOptionValue(optionsObj, "valueAsBuffer", true);
+  bool fillCache = BooleanOptionValue(optionsObj, "fillCache");
 
   Iterator* iterator = new Iterator(
       database
@@ -447,9 +485,9 @@ NAN_METHOD(Iterator::New) {
     , startHandle
     , highWaterMark
   );
-  iterator->Wrap(args.This());
+  iterator->Wrap(info.This());
 
-  NanReturnValue(args.This());
+  info.GetReturnValue().Set(info.This());
 }
 
 } // namespace leveldown
diff --git a/src/iterator.h b/src/iterator.h
index ae2b353..f38c58c 100644
--- a/src/iterator.h
+++ b/src/iterator.h
@@ -19,7 +19,7 @@ namespace leveldown {
 class Database;
 class AsyncWorker;
 
-class Iterator : public node::ObjectWrap {
+class Iterator : public Nan::ObjectWrap {
 public:
   static void Init ();
   static v8::Local<v8::Object> NewInstance (
@@ -62,6 +62,7 @@ private:
   leveldb::ReadOptions* options;
   leveldb::Slice* start;
   std::string* end;
+  bool seeking;
   bool reverse;
   bool keys;
   bool values;
@@ -81,12 +82,13 @@ public:
   AsyncWorker* endWorker;
 
 private:
-  v8::Persistent<v8::Object> persistentHandle;
+  Nan::Persistent<v8::Object> persistentHandle;
 
   bool Read (std::string& key, std::string& value);
   bool GetIterator ();
 
   static NAN_METHOD(New);
+  static NAN_METHOD(Seek);
   static NAN_METHOD(Next);
   static NAN_METHOD(End);
 };
diff --git a/src/iterator_async.cc b/src/iterator_async.cc
index fffbbd4..6da6e65 100644
--- a/src/iterator_async.cc
+++ b/src/iterator_async.cc
@@ -17,7 +17,7 @@ namespace leveldown {
 
 NextWorker::NextWorker (
     Iterator* iterator
-  , NanCallback *callback
+  , Nan::Callback *callback
   , void (*localCallback)(Iterator*)
 ) : AsyncWorker(NULL, callback)
   , iterator(iterator)
@@ -36,7 +36,7 @@ void NextWorker::HandleOKCallback () {
   size_t idx = 0;
 
   size_t arraySize = result.size() * 2;
-  v8::Local<v8::Array> returnArray = NanNew<v8::Array>(arraySize);
+  v8::Local<v8::Array> returnArray = Nan::New<v8::Array>(arraySize);
 
   for(idx = 0; idx < result.size(); ++idx) {
     std::pair<std::string, std::string> row = result[idx];
@@ -45,31 +45,33 @@ void NextWorker::HandleOKCallback () {
 
     v8::Local<v8::Value> returnKey;
     if (iterator->keyAsBuffer) {
-      returnKey = NanNewBufferHandle((char*)key.data(), key.size());
+      //TODO: use NewBuffer, see database_async.cc
+      returnKey = Nan::CopyBuffer((char*)key.data(), key.size()).ToLocalChecked();
     } else {
-      returnKey = NanNew<v8::String>((char*)key.data(), key.size());
+      returnKey = Nan::New<v8::String>((char*)key.data(), key.size()).ToLocalChecked();
     }
 
     v8::Local<v8::Value> returnValue;
     if (iterator->valueAsBuffer) {
-      returnValue = NanNewBufferHandle((char*)value.data(), value.size());
+      //TODO: use NewBuffer, see database_async.cc
+      returnValue = Nan::CopyBuffer((char*)value.data(), value.size()).ToLocalChecked();
     } else {
-      returnValue = NanNew<v8::String>((char*)value.data(), value.size());
+      returnValue = Nan::New<v8::String>((char*)value.data(), value.size()).ToLocalChecked();
     }
 
     // put the key & value in a descending order, so that they can be .pop:ed in javascript-land
-    returnArray->Set(NanNew<v8::Integer>(static_cast<int>(arraySize - idx * 2 - 1)), returnKey);
-    returnArray->Set(NanNew<v8::Integer>(static_cast<int>(arraySize - idx * 2 - 2)), returnValue);
+    returnArray->Set(Nan::New<v8::Integer>(static_cast<int>(arraySize - idx * 2 - 1)), returnKey);
+    returnArray->Set(Nan::New<v8::Integer>(static_cast<int>(arraySize - idx * 2 - 2)), returnValue);
   }
 
   // clean up & handle the next/end state see iterator.cc/checkEndCallback
   localCallback(iterator);
 
   v8::Local<v8::Value> argv[] = {
-      NanNull()
+      Nan::Null()
     , returnArray
     // when ok === false all data has been read, so it's then finished
-    , NanNew<v8::Boolean>(!ok)
+    , Nan::New<v8::Boolean>(!ok)
   };
   callback->Call(3, argv);
 }
@@ -78,12 +80,12 @@ void NextWorker::HandleOKCallback () {
 
 EndWorker::EndWorker (
     Iterator* iterator
-  , NanCallback *callback
+  , Nan::Callback *callback
 ) : AsyncWorker(NULL, callback)
   , iterator(iterator)
 {};
 
-EndWorker::~EndWorker () {}
+EndWorker::~EndWorker () { }
 
 void EndWorker::Execute () {
   iterator->IteratorEnd();
diff --git a/src/iterator_async.h b/src/iterator_async.h
index 9d6c7a3..d4fa47b 100644
--- a/src/iterator_async.h
+++ b/src/iterator_async.h
@@ -18,7 +18,7 @@ class NextWorker : public AsyncWorker {
 public:
   NextWorker (
       Iterator* iterator
-    , NanCallback *callback
+    , Nan::Callback *callback
     , void (*localCallback)(Iterator*)
   );
 
@@ -37,7 +37,7 @@ class EndWorker : public AsyncWorker {
 public:
   EndWorker (
       Iterator* iterator
-    , NanCallback *callback
+    , Nan::Callback *callback
   );
 
   virtual ~EndWorker ();
diff --git a/src/leveldown.cc b/src/leveldown.cc
index 2a4ed31..fc95c61 100644
--- a/src/leveldown.cc
+++ b/src/leveldown.cc
@@ -14,60 +14,60 @@
 namespace leveldown {
 
 NAN_METHOD(DestroyDB) {
-  NanScope();
+  Nan::HandleScope scope;
 
-  NanUtf8String* location = new NanUtf8String(args[0]);
+  Nan::Utf8String* location = new Nan::Utf8String(info[0]);
 
-  NanCallback* callback = new NanCallback(
-      v8::Local<v8::Function>::Cast(args[1]));
+  Nan::Callback* callback = new Nan::Callback(
+      v8::Local<v8::Function>::Cast(info[1]));
 
   DestroyWorker* worker = new DestroyWorker(
       location
     , callback
   );
 
-  NanAsyncQueueWorker(worker);
+  Nan::AsyncQueueWorker(worker);
 
-  NanReturnUndefined();
+  info.GetReturnValue().SetUndefined();
 }
 
 NAN_METHOD(RepairDB) {
-  NanScope();
+  Nan::HandleScope scope;
 
-  NanUtf8String* location = new NanUtf8String(args[0]);
+  Nan::Utf8String* location = new Nan::Utf8String(info[0]);
 
-  NanCallback* callback = new NanCallback(
-      v8::Local<v8::Function>::Cast(args[1]));
+  Nan::Callback* callback = new Nan::Callback(
+      v8::Local<v8::Function>::Cast(info[1]));
 
   RepairWorker* worker = new RepairWorker(
       location
     , callback
   );
 
-  NanAsyncQueueWorker(worker);
+  Nan::AsyncQueueWorker(worker);
 
-  NanReturnUndefined();
+  info.GetReturnValue().SetUndefined();
 }
 
-void Init (v8::Handle<v8::Object> target) {
+void Init (v8::Local<v8::Object> target) {
   Database::Init();
   leveldown::Iterator::Init();
   leveldown::Batch::Init();
 
   v8::Local<v8::Function> leveldown =
-      NanNew<v8::FunctionTemplate>(LevelDOWN)->GetFunction();
+      Nan::New<v8::FunctionTemplate>(LevelDOWN)->GetFunction();
 
   leveldown->Set(
-      NanNew("destroy")
-    , NanNew<v8::FunctionTemplate>(DestroyDB)->GetFunction()
+      Nan::New("destroy").ToLocalChecked()
+    , Nan::New<v8::FunctionTemplate>(DestroyDB)->GetFunction()
   );
 
   leveldown->Set(
-      NanNew("repair")
-    , NanNew<v8::FunctionTemplate>(RepairDB)->GetFunction()
+      Nan::New("repair").ToLocalChecked()
+    , Nan::New<v8::FunctionTemplate>(RepairDB)->GetFunction()
   );
 
-  target->Set(NanNew("leveldown"), leveldown);
+  target->Set(Nan::New("leveldown").ToLocalChecked(), leveldown);
 }
 
 NODE_MODULE(leveldown, Init)
diff --git a/src/leveldown.h b/src/leveldown.h
index a704c06..43dbaa0 100644
--- a/src/leveldown.h
+++ b/src/leveldown.h
@@ -11,6 +11,8 @@
 #include <nan.h>
 
 static inline size_t StringOrBufferLength(v8::Local<v8::Value> obj) {
+  Nan::HandleScope scope;
+
   return (!obj->ToObject().IsEmpty()
     && node::Buffer::HasInstance(obj->ToObject()))
     ? node::Buffer::Length(obj->ToObject())
@@ -20,16 +22,17 @@ static inline size_t StringOrBufferLength(v8::Local<v8::Value> obj) {
 // NOTE: this MUST be called on objects created by
 // LD_STRING_OR_BUFFER_TO_SLICE
 static inline void DisposeStringOrBufferFromSlice(
-        v8::Persistent<v8::Object> &handle
+        Nan::Persistent<v8::Object> &handle
       , leveldb::Slice slice) {
+  Nan::HandleScope scope;
 
   if (!slice.empty()) {
-    v8::Local<v8::Value> obj = NanNew<v8::Object>(handle)->Get(NanNew<v8::String>("obj"));
+    v8::Local<v8::Value> obj = Nan::New<v8::Object>(handle)->Get(Nan::New<v8::String>("obj").ToLocalChecked());
     if (!node::Buffer::HasInstance(obj))
       delete[] slice.data();
   }
 
-  NanDisposePersistent(handle);
+  handle.Reset();
 }
 
 static inline void DisposeStringOrBufferFromSlice(
@@ -66,41 +69,42 @@ static inline void DisposeStringOrBufferFromSlice(
 #define LD_RETURN_CALLBACK_OR_ERROR(callback, msg)                             \
   if (!callback.IsEmpty() && callback->IsFunction()) {                         \
     v8::Local<v8::Value> argv[] = {                                            \
-      NanError(msg)                                                            \
+      Nan::Error(msg)                                                          \
     };                                                                         \
     LD_RUN_CALLBACK(callback, 1, argv)                                         \
-    NanReturnUndefined();                                                      \
+    info.GetReturnValue().SetUndefined();                                      \
+    return;                                                                    \
   }                                                                            \
-  return NanThrowError(msg);
+  return Nan::ThrowError(msg);
 
 #define LD_RUN_CALLBACK(callback, argc, argv)                                  \
-  NanMakeCallback(                                                          \
-      NanGetCurrentContext()->Global(), callback, argc, argv);
+  Nan::MakeCallback(                                                           \
+      Nan::GetCurrentContext()->Global(), callback, argc, argv);
 
 /* 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)
+ *  - Nan::Persistent<v8::Function> callback (won't be empty)
  * 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)                                                      \
-    return NanThrowError(#name "() requires a callback argument");             \
+  if (info.Length() == 0)                                                      \
+    return Nan::ThrowError(#name "() requires a callback argument");           \
   leveldown::Database* database =                                              \
-    node::ObjectWrap::Unwrap<leveldown::Database>(args.This());                \
+    Nan::ObjectWrap::Unwrap<leveldown::Database>(info.This());                 \
   v8::Local<v8::Object> optionsObj;                                            \
   v8::Local<v8::Function> callback;                                            \
-  if (optionPos == -1 && args[callbackPos]->IsFunction()) {                    \
-    callback = args[callbackPos].As<v8::Function>();                           \
-  } else if (optionPos != -1 && args[callbackPos - 1]->IsFunction()) {         \
-    callback = args[callbackPos - 1].As<v8::Function>();                       \
+  if (optionPos == -1 && info[callbackPos]->IsFunction()) {                    \
+    callback = info[callbackPos].As<v8::Function>();                           \
+  } else if (optionPos != -1 && info[callbackPos - 1]->IsFunction()) {         \
+    callback = info[callbackPos - 1].As<v8::Function>();                       \
   } else if (optionPos != -1                                                   \
-        && args[optionPos]->IsObject()                                         \
-        && args[callbackPos]->IsFunction()) {                                  \
-    optionsObj = args[optionPos].As<v8::Object>();                             \
-    callback = args[callbackPos].As<v8::Function>();                           \
+        && info[optionPos]->IsObject()                                         \
+        && info[callbackPos]->IsFunction()) {                                  \
+    optionsObj = info[optionPos].As<v8::Object>();                             \
+    callback = info[callbackPos].As<v8::Function>();                           \
   } else {                                                                     \
-    return NanThrowError(#name "() requires a callback argument");             \
+    return Nan::ThrowError(#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 675a234..dfaa5a3 100644
--- a/src/leveldown_async.cc
+++ b/src/leveldown_async.cc
@@ -13,8 +13,8 @@ namespace leveldown {
 /** DESTROY WORKER **/
 
 DestroyWorker::DestroyWorker (
-    NanUtf8String* location
-  , NanCallback *callback
+    Nan::Utf8String* location
+  , Nan::Callback *callback
 ) : AsyncWorker(NULL, callback)
   , location(location)
 {};
@@ -31,8 +31,8 @@ void DestroyWorker::Execute () {
 /** REPAIR WORKER **/
 
 RepairWorker::RepairWorker (
-    NanUtf8String* location
-  , NanCallback *callback
+    Nan::Utf8String* location
+  , Nan::Callback *callback
 ) : AsyncWorker(NULL, callback)
   , location(location)
 {};
diff --git a/src/leveldown_async.h b/src/leveldown_async.h
index 689342d..53196e5 100644
--- a/src/leveldown_async.h
+++ b/src/leveldown_async.h
@@ -15,29 +15,29 @@ namespace leveldown {
 class DestroyWorker : public AsyncWorker {
 public:
   DestroyWorker (
-      NanUtf8String* location
-    , NanCallback *callback
+      Nan::Utf8String* location
+    , Nan::Callback *callback
   );
 
   virtual ~DestroyWorker ();
   virtual void Execute ();
 
 private:
-  NanUtf8String* location;
+  Nan::Utf8String* location;
 };
 
 class RepairWorker : public AsyncWorker {
 public:
   RepairWorker (
-      NanUtf8String* location
-    , NanCallback *callback
+      Nan::Utf8String* location
+    , Nan::Callback *callback
   );
 
   virtual ~RepairWorker ();
   virtual void Execute ();
 
 private:
-  NanUtf8String* location;
+  Nan::Utf8String* location;
 };
 
 } // namespace leveldown
diff --git a/test/compression-test.js b/test/compression-test.js
new file mode 100644
index 0000000..af86e2c
--- /dev/null
+++ b/test/compression-test.js
@@ -0,0 +1,92 @@
+/* Copyright (c) 2012-2015 LevelUP contributors
+ * See list at <https://github.com/level/leveldown#contributing>
+ * MIT License <https://github.com/level/leveldown/blob/master/LICENSE.md>
+ */
+
+var async      = require('async')
+  , du         = require('du')
+  , delayed    = require('delayed')
+  , common     = require('abstract-leveldown/testCommon')
+  , leveldown  = require('../')
+  , test       = require('tape')
+
+  , compressableData = new Buffer(Array.apply(null, Array(1024 * 100)).map(function () { return 'aaaaaaaaaa' }).join(''))
+  , multiples = 10
+  , dataSize = compressableData.length * multiples
+
+  , verify = function (location, compression, t) {
+      du(location, function (err, size) {
+        t.error(err)
+        if (compression)
+          t.ok(size < dataSize, 'on-disk size (' + size + ') is less than data size (' + dataSize + ')')
+        else
+          t.ok(size >= dataSize, 'on-disk size (' + size + ') is greater than data size (' + dataSize + ')')
+        t.end()
+      })
+    }
+
+    // close, open, close again.. 'compaction' is also performed on open()s
+  , cycle = function (db, compression, t, callback) {
+      var location = db.location
+      db.close(function (err) {
+        t.error(err)
+        db = leveldown(location)
+        db.open({ errorIfExists: false, compression: compression }, function () {
+          t.error(err)
+          db.close(function (err) {
+            t.error(err)
+            callback()
+          })
+        })
+      })
+    }
+
+test('Compression', function (t) {
+  t.test('set up', common.setUp)
+
+  t.test('test data is compressed by default (db.put())', function (t) {
+    var db = leveldown(common.location())
+    db.open(function (err) {
+      t.error(err)
+      async.forEach(
+          Array.apply(null, Array(multiples)).map(function (e, i) {
+            return [ i, compressableData ]
+          })
+        , function (args, callback) {
+            db.put.apply(db, args.concat([callback]))
+          }
+        , cycle.bind(null, db, true, t, delayed.delayed(verify.bind(null, db.location, true, t), 0.01))
+      )
+    })
+  })
+
+  t.test('test data is not compressed with compression=false on open() (db.put())', function (t) {
+    var db = leveldown(common.location())
+    db.open({ compression: false }, function (err) {
+      t.error(err)
+      async.forEach(
+          Array.apply(null, Array(multiples)).map(function (e, i) {
+            return [ i, compressableData ]
+          })
+        , function (args, callback) {
+            db.put.apply(db, args.concat([callback]))
+          }
+        , cycle.bind(null, db, false, t, delayed.delayed(verify.bind(null, db.location, false, t), 0.01))
+      )
+    })
+  })
+
+  t.test('test data is compressed by default (db.batch())', function (t) {
+    var db = leveldown(common.location())
+    db.open(function (err) {
+      t.error(err)
+      db.batch(
+          Array.apply(null, Array(multiples)).map(function (e, i) {
+            return { type: 'put', key: i, value: compressableData }
+          })
+        , cycle.bind(null, db, false, t, delayed.delayed(verify.bind(null, db.location, false, t), 0.01))
+      )
+    })
+  })
+})
+
diff --git a/test/iterator-test.js b/test/iterator-test.js
index 1c179a9..87db93b 100644
--- a/test/iterator-test.js
+++ b/test/iterator-test.js
@@ -2,5 +2,68 @@ const test       = require('tape')
     , testCommon = require('abstract-leveldown/testCommon')
     , leveldown  = require('../')
     , abstract   = require('abstract-leveldown/abstract/iterator-test')
+    , make       = require('./make')
 
 abstract.all(leveldown, test, testCommon)
+
+make('iterator throws if key is not a string', function (db, t, done) {
+  var ite = db.iterator()
+  var error
+  try {
+    ite.seek()
+  } catch (e) {
+    error = e
+  }
+
+  t.ok(error, 'had error')
+  t.end()
+})
+
+make('iterator is seekable', function (db, t, done) {
+  var ite = db.iterator()
+  ite.seek('two')
+  ite.next(function (err, key, value) {
+    t.error(err, 'no error')
+    t.same(key.toString(), 'two', 'key matches')
+    t.same(value.toString(), '2', 'value matches')
+    ite.next(function (err, key, value) {
+      t.error(err, 'no error')
+      t.same(key, undefined, 'end of iterator')
+      t.same(value, undefined, 'end of iterator')
+      ite.end(done)
+    })
+  })
+})
+
+make('reverse seek in the middle', function (db, t, done) {
+  var ite = db.iterator({reverse: true, limit: 1})
+  ite.seek('three!')
+  ite.next(function (err, key, value) {
+    t.error(err, 'no error')
+    t.same(key.toString(), 'three', 'key matches')
+    t.same(value.toString(), '3', 'value matches')
+    ite.end(done)
+  })
+})
+
+make('iterator invalid seek', function (db, t, done) {
+  var ite = db.iterator()
+  ite.seek('zzz')
+  ite.next(function (err, key, value) {
+    t.error(err, 'no error')
+    t.same(key, undefined, 'end of iterator')
+    t.same(value, undefined, 'end of iterator')
+    ite.end(done)
+  })
+})
+
+make('reverse seek from invalid range', function (db, t, done) {
+  var ite = db.iterator({reverse: true})
+  ite.seek('zzz')
+  ite.next(function (err, key, value) {
+    t.error(err, 'no error')
+    t.same(key.toString(), 'two', 'end of iterator')
+    t.same(value.toString(), '2', 'end of iterator')
+    ite.end(done)
+  })
+})

-- 
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