[Pkg-javascript-commits] [node-sqlite3] 01/10: Imported Upstream version 3.1.3+ds1

László Böszörményi gcs at moszumanska.debian.org
Sun Apr 24 08:52:12 UTC 2016


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

gcs pushed a commit to branch master
in repository node-sqlite3.

commit 97ad028d211f148e61dd7ad64ecdc3ed19e89009
Author: Laszlo Boszormenyi (GCS) <gcs at debian.org>
Date:   Sun Apr 24 08:31:18 2016 +0000

    Imported Upstream version 3.1.3+ds1
---
 .gitignore                           |   7 +-
 .npmignore                           |  12 +
 .travis.yml                          | 160 ++++++++-----
 CHANGELOG.md                         | 146 +++++++++++-
 CONTRIBUTING.md                      |  57 +++++
 Makefile                             |  50 +++-
 README.md                            | 144 ++++++-----
 appveyor.yml                         |  56 +++++
 binding.gyp                          |  20 +-
 configure                            |   3 -
 deps/common-sqlite.gypi              |  55 ++++-
 deps/sqlite3.gyp                     |   8 +-
 lib/binary_name.js                   |  59 -----
 lib/sqlite3.js                       | 115 ++++-----
 package.json                         |  37 +--
 scripts/build-appveyor.bat           | 160 +++++++++++++
 scripts/build-local.bat              |  59 +++++
 scripts/build.bat                    |  49 ----
 scripts/build_against_node.sh        |  79 ++++++
 scripts/build_against_node_webkit.sh |  91 +++++++
 scripts/build_for_node_webkit.cmd    |  15 ++
 scripts/install_node.sh              |  21 ++
 scripts/validate_tag.sh              |  24 ++
 src/async.h                          |   2 +-
 src/database.cc                      | 347 ++++++++++++++-------------
 src/database.h                       |  61 ++---
 src/gcc-preinclude.h                 |   2 +
 src/macros.h                         | 105 ++++----
 src/node_sqlite3.cc                  |   9 +-
 src/statement.cc                     | 449 ++++++++++++++++++-----------------
 src/statement.h                      |  58 ++---
 test/json.test.js                    |  22 ++
 test/named_columns.test.js           |   9 +
 test/nw/Makefile                     |  11 +-
 test/prepare.test.js                 |  51 ++++
 test/profile.test.js                 |   7 +-
 test/unicode.test.js                 |  73 +++++-
 37 files changed, 1783 insertions(+), 850 deletions(-)

diff --git a/.gitignore b/.gitignore
index b62f417..1197bbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,9 @@
-.lock-wscript
 *.dylib
 *.so
 *.o
 *.lo
 *.Makefile
 *.target.gyp.mk
-stage
 lib/binding
 build
 out
@@ -18,6 +16,7 @@ gyp-mac-tool
 .dirstamp
 npm-debug.log
 test/support/big.db
-lib/node_sqlite3.node
 test/tmp
-.DS_Store
\ No newline at end of file
+test/nw/app.nw
+.DS_Store
+.idea
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..733dbe7
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,12 @@
+.gitignore
+.npmignore
+node_modules
+lib/binding
+build
+test
+benchmark
+configure
+Makefile
+scripts
+.travis.yml
+examples
diff --git a/.travis.yml b/.travis.yml
index 92ac5dd..64d73b7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,67 +1,115 @@
-language: cpp
+sudo: false
+
+language: generic
+
+git:
+  depth: 10
+
+addons:
+  apt:
+    sources:
+    - ubuntu-toolchain-r-test
+    - llvm-toolchain-precise-3.5
+    packages:
+     - clang-3.5
+
+# don't re-build for tags so that [publish binary] is not re-run
+# https://github.com/travis-ci/travis-ci/issues/1532
+branches:
+  except:
+    - /^v[0-9]/
+
+matrix:
+  include:
+     # Linux
+     - os: linux
+       compiler: clang
+       env: NODE_VERSION="5"
+       addons:
+         apt:
+            sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ]
+            packages: [ 'clang-3.5']
+     - os: linux
+       compiler: clang
+       env: NODE_VERSION="4"
+       addons:
+         apt:
+            sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ]
+            packages: [ 'clang-3.5']
+     - os: linux
+       compiler: clang
+       env: NODE_VERSION="0.12"
+       addons:
+         apt:
+            sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ]
+            packages: [ 'clang-3.5']
+     - os: linux
+       compiler: clang
+       env: NODE_VERSION="0.10"
+       addons:
+         apt:
+            sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ]
+            packages: [ 'clang-3.5']
+     # test building against external sqlite
+     - os: linux
+       compiler: clang
+       env: NODE_VERSION="0.10.40" EXTERNAL_SQLITE=true PUBLISHABLE=false
+       addons:
+         apt:
+            sources: [ 'ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5', 'gcc-multilib', 'g++-multilib', 'libsqlite3-dev:i386' ]
+            packages: [ 'clang-3.5','libsqlite3-dev']
+     # OS X
+     - os: osx
+       compiler: clang
+       env: NODE_VERSION="5" COVERAGE=true PUBLISHABLE=false # node abi 47
+     - os: osx
+       compiler: clang
+       env: NODE_VERSION="5" # node abi 47
+     - os: osx
+       compiler: clang
+       env: NODE_VERSION="4" # node abi 46
+     - os: osx
+       compiler: clang
+       env: NODE_VERSION="0.12" # node abi 14
+     - os: osx
+       compiler: clang
+       env: NODE_VERSION="0.10" # node abi 11
 
 env:
-  matrix:
-   - export NODE_VERSION="0.8"
-   - export NODE_VERSION="0.10"
   global:
-    - secure: QhuP5E/kYL1j1KDkHGJtk6DSJr1RH4DR/JrC62Viuf5Du8jE+i0kPWfF2MxtuEmKo35orhpu8t8mzKygWfuO63WPuuIE9qd/+V/y99Lqcj0tEN6wJ5RnywktbTJWg23zphjhmYq3Xj8DLVEikCZBwHtlbygkO9Q60cn1PK+bnPg=
-    - secure: HxCS2dQAWI0KmCFnFNNZoucG4FeAW+itG7+Hp0dNtwmxZzGOZYFO2bZcGvTAMNfVN++oqLxTebYQI1oB5yUl5mPJjrjthaGS6Zq3S6rfJcXiv+icYgEXlR6ejQ97dsHw1Jeg8nedCQlI4kHfvG6pgBLhq9hnugxH1Cjhdt14E9U=
+    - JOBS: "8"
+    - secure: PifMOSnn+mWR1RUptXse+fLvWiTrzg0R/mazO7RWhXHWBKv0uAJ/qV3dI0GIRBLtjG10Iy+tT5RNh1TIbBzB9Y67wMcGvylUPG1+3EOKoBMEPnOD9AgCEQw4SOXfGPx0cq2N6ueSKieCgu1yKN9Wq7XCbE+zTk/DiRNIdLirVoo=
+    - secure: cc4esJY1vPXL31IeumAJoKWDDO2BTGFiltwfO1jbTbiV7QT911QUjTUasxXIVpOaHNCpxSTyevPwwTWfzt2EtF92Lli+qhQ2bbzMiDSBZstSrHdAe62Ai2M1oYYUwk/0cABB/2nO9uRyYwITCxpTSNzZBrYhn3C29WqBhPeVDmM=
 
 before_install:
-# put node-pre-gyp on path
-- export PATH=./node_modules/.bin/:$PATH
-- echo $NODE_VERSION
-- git clone https://github.com/creationix/nvm.git ../.nvm
-- source ../.nvm/nvm.sh
-- nvm install $NODE_VERSION
-- nvm use $NODE_VERSION
-- node --version
-- npm --version
-- npm install mocha
-- platform=$(uname -s | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/")
+- export PUBLISHABLE=${PUBLISHABLE:-true}
+- export COVERAGE=${COVERAGE:-false}
+- if [[ $(uname -s) == 'Linux' ]]; then
+    export CXX="clang++-3.5";
+    export CC="clang-3.5";
+    export PYTHONPATH=$(pwd)/py-local/lib/python2.7/site-packages;
+  else
+    export PYTHONPATH=$(pwd)/py-local/lib/python/site-packages;
+  fi;
+- scripts/validate_tag.sh
+- source ./scripts/install_node.sh ${NODE_VERSION}
 
 install:
-# test installing from source
-- npm install --build-from-source
-- npm test
+# put node-pre-gyp on path
+- export PATH=./node_modules/.bin/:$PATH
 
 before_script:
-# test publishing
-- echo $TRAVIS_BRANCH
-- echo $TRAVIS_COMMIT
-- echo `git describe --tags --always HEAD`
-- PUBLISH=false
-- if [ "[publish]" = `git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n'` ]; then echo yes;PUBLISH=true; fi;
-- if [[ `git describe --contains $( git rev-parse HEAD )` ]]; then echo yes;PUBLISH=true; fi;
-- if [[ $PUBLISH == true ]]; then node-pre-gyp package publish; fi
+# get commit message
+- export COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n')
+- if [[ ${COVERAGE} == true ]]; then
+     if [[ $(uname -s) == 'Linux' ]]; then
+       PYTHONUSERBASE=$(pwd)/py-local pip install --user cpp-coveralls;
+     else
+       PYTHONUSERBASE=$(pwd)/py-local easy_install --user cpp-coveralls;
+     fi;
+   fi
 
 script:
-# test install from published binary
-- make clean
-- npm install
-- npm test
-- make clean
-# test source compile against system libsqlite3
-- if [[ "$platform" == 'linux' ]]; then sudo apt-get -qq update; sudo apt-get -qq install libsqlite3-dev; fi
-- make clean
-- npm install --build-from-source --sqlite=/usr
-- npm test
-- make clean
-# node v0.8 and above provide pre-built 32 bit and 64 bit binaries
-# so here we use the 32 bit ones to also test 32 bit builds
-- NVER=`node -v`
-- wget http://nodejs.org/dist/${NVER}/node-${NVER}-${platform}-x86.tar.gz
-- tar xf node-${NVER}-${platform}-x86.tar.gz
-# enable 32 bit node
-- export PATH=$(pwd)/node-${NVER}-${platform}-x86/bin:$PATH
-# install 32 bit compiler toolchain
-- if [[ "$platform" == 'linux' ]]; then sudo apt-get -y install gcc-multilib g++-multilib; fi
-# test source compile in 32 bit mode with internal libsqlite3
-- if [[ "$platform" == 'linux' ]]; then CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source; else npm install --build-from-source; fi
-- npm test
-# publish 32 bit build
-- if [[ $PUBLISH == true ]]; then node-pre-gyp package publish; fi;
-- make clean
-# test source compile in 32 bit mode against external libsqlite3
-- if [[ "$platform" == 'linux' ]]; then sudo apt-get -y install libsqlite3-dev:i386; CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source --sqlite=/usr; npm test; fi
+- if [[ "${NODE_VERSION}" ]]; then ./scripts/build_against_node.sh; fi;
+# disabled for now: need to port to sudo:false
+#- if [[ "${NODE_WEBKIT}" ]]; then ./scripts/build_against_node_webkit.sh; fi;
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2f08d2..3cd2f9f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,146 @@
-# Changlog
+# Changelog
+
+## 3.1.3
+
+ - Upgrade to node-pre-gyp at 0.6.26 with better support for Electron
+
+## 3.1.2
+
+ - Only providing binaries for node v0.10x, v0.12.x, v4, and v5
+ - Upgrade to nan at 2.2.x
+ - Upgrade to node-pre-gyp at 0.6.24
+
+
+## 3.1.1
+
+ - Support for node 5.x
+ - Upgraded SQLite to 3.9.1: https://www.sqlite.org/releaselog/3_9_1.html
+ - Enabled json1 extension by default 
+
+## 3.1.0
+
+ - Support for node 3.x and 4.x
+ - Stopped producing binaries for node-webkit and 32 bit linux
+
+## 3.0.11
+
+ - Support for io.js 3.x (upgrade to Nan 2.x) @kkoopa
+
+## 3.0.10
+
+ - Upgraded SQLite to 3.8.11.1: https://www.sqlite.org/releaselog/3_8_11_1.html
+ - Fixed binary compatibility regression with old centos/rhel glibc GLIBC_2.14 (re-introduced alpine linux (musl) build regression)
+ - Now providing binaries against Visual Studio 2015 (pass --toolset=v140) and use binaries from https://github.com/mapbox/node-cpp11
+
+## 3.0.9
+
+ - Fixed build regression against alpine linux (musl)
+ - Upgraded node-pre-gyp at 0.6.8
+
+## 3.0.8
+
+ - Fixed build regression against FreeBSD
+ - Upgraded node-pre-gyp at 0.6.7
+
+## 3.0.7
+
+ - Fixed build regression against ARM and i386 linux
+ - Upgraded node-pre-gyp at 0.6.6
+ - Added support for io.js 2.0.0
+
+## 3.0.6
+
+ - Upgraded node-pre-gyp at 0.6.5
+ - Upgraded nan at 1.8.4
+ - Fixed binaries to work on older linux systems (circa GLIBC_2.2.5 like centos 6) @bnoordhuis
+ - Updated internal libsqlite3 from 3.8.7.1 -> 3.8.9 (http://www.sqlite.org/news.html)
+
+## 3.0.5
+
+ - IO.js and Node v0.12.x support.
+ - Node-webkit v0.11.x support regressed in this release, sorry (https://github.com/mapbox/node-sqlite3/issues/404).
+
+## 3.0.4
+
+ - Upgraded node-pre-gyp at 0.6.1
+
+## 3.0.3
+
+ - Upgraded to node-pre-gyp at 0.6.0 which should fix crashes against node v0.11.14
+ - Now providing binaries against Visual Studio 2014 (pass --toolset=v140) and use binaries from https://github.com/mapbox/node-cpp11
+
+## 3.0.2
+
+ - Republish for possibly busted npm package.
+
+## 3.0.1
+
+ - Use ~ in node-pre-gyp semver for more flexible dep management.
+
+## 3.0.0
+
+Released September 20nd, 2014
+
+ - Backwards-incompatible change: node versions 0.8.x are no longer supported.
+ - Updated to node-pre-gyp at 0.5.27
+ - Updated NAN to 1.3.0
+ - Updated internal libsqlite3 to v3.8.6
+
+## 2.2.7
+
+Released August 6th, 2014
+
+ - Removed usage of `npm ls` with `prepublish` target (which breaks node v0.8.x)
+
+## 2.2.6
+
+Released August 6th, 2014
+
+ - Fix bundled version of node-pre-gyp
+
+## 2.2.5
+
+Released August 5th, 2014
+
+ - Fix leak in complete() callback of Database.each() (#307)
+ - Started using `engineStrict` and improved `engines` declaration to make clear only >= 0.11.13 is supported for the 0.11.x series.
+
+## 2.2.4
+
+Released July 14th, 2014
+
+ - Now supporting node v0.11.x (specifically >=0.11.13)
+ - Fix db opening error with absolute path on windows
+ - Updated to node-pre-gyp at 0.5.18
+ - updated internal libsqlite3 from 3.8.4.3 -> 3.8.5 (http://www.sqlite.org/news.html)
+
+## 2.2.3
+
+ - Fixed regression in v2.2.2 for installing from binaries on windows.
+
+## 2.2.2
+
+ - Fixed packaging problem whereby a `config.gypi` was unintentially packaged and could cause breakages for OS X builds.
+
+## 2.2.1
+
+ - Now shipping with 64bit FreeBSD binaries against both node v0.10.x and node v0.8.x.
+ - Fixed solaris/smartos source compile by passing `-std=c99` when building internally bundled libsqlite3 (#201)
+ - Reduced size of npm package by ignoring tests and examples.
+ - Various fixes and improvements for building against node-webkit
+ - Upgraded to node-pre-gyp at 0.5.x from node-pre-gyp at 0.2.5
+ - Improved ability to build from source against `sqlcipher` by passing custom library name: `--sqlite_libname=sqlcipher`
+ - No changes to C++ Core / Existing binaries are exactly the same
+
+## 2.2.0
+
+Released Jan 13th, 2014
+
+ - updated internal libsqlite3 from 3.7.17 -> 3.8.2 (http://www.sqlite.org/news.html) which includes the next-generation query planner http://www.sqlite.org/queryplanner-ng.html
+ - improved binary deploy system using https://github.com/springmeyer/node-pre-gyp
+ - binary install now supports http proxies
+ - source compile now supports freebsd
+ - fixed support for node-webkit
 
 ## 2.1.19
 
@@ -26,5 +168,3 @@ Released October 22nd, 2013
 Released August 7th, 2013
 
  - Minor readme additions and code optimizations
-
-
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..3801e30
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,57 @@
+# Contributing
+
+General guidelines for contributing to node-sqlite3
+
+## Install Help
+
+If you've landed here due to a failed install of `node-sqlite3` then feel free to create a [new issue](https://github.com/mapbox/node-sqlite3/issues/new) to ask for help. The most likely problem is that we do not yet provide pre-built binaries for your particular platform and so the `node-sqlite3` install attempted a source compile but failed because you are missing the [dependencies for node-gyp](https://github.com/TooTallNate/node-gyp#installation). But please provide as much detail on [...]
+ - terminal logs of failed install (preferably from running `npm install sqlite3 --loglevel=info`)
+ - `node-sqlite3` version you tried to install
+ - node version you are running
+ - operating system and architecture you are running, e.g. `Windows 7 64 bit`.
+
+## Developing / Pre-release
+
+Create a milestone for the next release on github. If all anticipated changes are back compatible then a `patch` release is in order. If minor API changes are needed then a `minor` release is in order. And a `major` bump is warranted if major API changes are needed.
+
+Assign tickets and pull requests you are working to the milestone you created.
+
+## Releasing
+
+To release a new version:
+
+**1)** Ensure tests are passing
+
+Before considering a release all the tests need to be passing on appveyor and travis.
+
+**2)** Bump commit
+
+Bump the version in `package.json` like https://github.com/mapbox/node-sqlite3/commit/77d51d5785b047ff40f6a8225051488a0d96f7fd
+
+What if you already committed the `package.json` bump and you have no changes to commit but want to publish binaries? In this case you can do:
+
+```sh
+git commit --allow-empty -m "[publish binary]"
+```
+
+**3)** Ensure binaries built
+
+Check the travis and appveyor pages to ensure they are all green as an indication that the `[publish binary]` command worked.
+
+If you need to republish binaries you can do this with the command below, however this should not be a common thing for you to do!
+
+```sh
+git commit --allow-empty -m "[republish binary]"
+```
+
+Note: NEVER republish binaries for an existing released version.
+
+**7)** Officially release
+
+An official release requires:
+
+ - Updating the CHANGELOG.md
+ - Create and push github tag like `git tag v3.1.1` -m "v3.1.1" && git push --tags`
+ - Ensure you have a clean checkout (no extra files in your check that are not known by git). You need to be careful, for instance, to avoid a large accidental file being packaged by npm. You can get a view of what npm will publish by running `make testpack`
+ - Fully rebuild and ensure install from binary works: `make clean && npm install --fallback-to-build=false`
+ - Then publish the module to npm repositories by running `npm publish`
diff --git a/Makefile b/Makefile
index c986b98..56fcb27 100644
--- a/Makefile
+++ b/Makefile
@@ -1,16 +1,46 @@
-build:
+#http://www.gnu.org/prep/standards/html_node/Standard-Targets.html#Standard-Targets
+
+all: build
+
+./node_modules:
 	npm install --build-from-source
 
+build: ./node_modules
+	./node_modules/.bin/node-pre-gyp build --loglevel=silent
+
+debug:
+	./node_modules/.bin/node-pre-gyp rebuild --debug
+
+verbose:
+	./node_modules/.bin/node-pre-gyp rebuild --loglevel=verbose
+
 clean:
-	rm -f ./lib/node_sqlite3.node
-	rm -rf ./lib/binding/
-	#rm -f ./test/support/big.db*
-	rm -f ./test/tmp/*
-	rm -rf ./deps/sqlite-autoconf-*/
-	rm -rf ./build
-	rm -rf ./out
+	@rm -rf ./build
+	rm -rf lib/binding/
+	rm -f test/support/big.db-journal
+	rm -rf ./node_modules/
 
+grind:
+	valgrind --leak-check=full node node_modules/.bin/_mocha
+
+testpack:
+	rm -f ./*tgz
+	npm pack
+	tar -ztvf *tgz
+	rm -f ./*tgz
+
+rebuild:
+	@make clean
+	@make
+
+ifndef only
 test:
-	npm test
+	@PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec
+else
+test:
+	@PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec test/${only}.test.js
+endif
+
+check: test
 
-.PHONY: build clean test
+.PHONY: test clean build
diff --git a/README.md b/README.md
index a9de89e..6f755fd 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,24 @@
-# NAME
+Asynchronous, non-blocking [SQLite3](http://sqlite.org/) bindings for [Node.js](http://nodejs.org/).
 
-node-sqlite3 - Asynchronous, non-blocking [SQLite3](http://sqlite.org/) bindings for [Node.js](http://nodejs.org/) 0.2-0.4 (versions 2.0.x), **0.6.13+, 0.8.x, and 0.10.x** (versions 2.1.x).
+[![NPM](https://nodei.co/npm/sqlite3.png?downloads=true&downloadRank=true)](https://nodei.co/npm/sqlite3/)
 
-(Can also run in [node-webkit](https://github.com/rogerwang/node-webkit) if it uses a supported version of Node's engine.)
+[![Build Status](https://travis-ci.org/mapbox/node-sqlite3.svg?branch=master)](https://travis-ci.org/mapbox/node-sqlite3)
+[![Build status](https://ci.appveyor.com/api/projects/status/gvm7ul0hpmdawqom)](https://ci.appveyor.com/project/Mapbox/node-sqlite3)
+[![Coverage Status](https://coveralls.io/repos/mapbox/node-sqlite3/badge.svg?branch=master&service=github)](https://coveralls.io/github/mapbox/node-sqlite3?branch=master)
+[![Dependencies](https://david-dm.org/mapbox/node-sqlite3.svg)](https://david-dm.org/mapbox/node-sqlite3)
 
-[![Build Status](https://travis-ci.org/mapbox/node-sqlite3.png?branch=master)](https://travis-ci.org/mapbox/node-sqlite3)
-[![npm package version](https://badge.fury.io/js/sqlite3.png)](https://npmjs.org/package/sqlite3)
 
+## Supported platforms
 
-# USAGE
+The `sqlite3` module works with Node.js v0.10.x, v0.12.x, v4.x, and v5.x.
+
+Binaries for most Node versions and platforms are provided by default via [node-pre-gyp](https://github.com/mapbox/node-pre-gyp).
+
+The `sqlite3` module also works with [node-webkit](https://github.com/rogerwang/node-webkit) if node-webkit contains a supported version of Node.js engine. [(See below.)](#building-for-node-webkit)
+
+SQLite's [SQLCipher extension](https://github.com/sqlcipher/sqlcipher) is also supported. [(See below.)](#building-for-sqlcipher)
+
+# Usage
 
 **Note:** the module must be [installed](#installing) before use.
 
@@ -33,18 +43,15 @@ db.serialize(function() {
 db.close();
 ```
 
+# Features
 
-
-# FEATURES
-
-* Straightforward query and parameter binding interface
-* Full Buffer/Blob support
-* Extensive [debugging support](https://github.com/mapbox/node-sqlite3/wiki/Debugging)
-* [Query serialization](https://github.com/mapbox/node-sqlite3/wiki/Control-Flow) API
-* [Extension support](https://github.com/mapbox/node-sqlite3/wiki/Extensions)
-* Big test suite
-* Written in modern C++ and tested for memory leaks
-
+ - Straightforward query and parameter binding interface
+ - Full Buffer/Blob support
+ - Extensive [debugging support](https://github.com/mapbox/node-sqlite3/wiki/Debugging)
+ - [Query serialization](https://github.com/mapbox/node-sqlite3/wiki/Control-Flow) API
+ - [Extension support](https://github.com/mapbox/node-sqlite3/wiki/Extensions)
+ - Big test suite
+ - Written in modern C++ and tested for memory leaks
 
 
 # API
@@ -52,7 +59,7 @@ db.close();
 See the [API documentation](https://github.com/mapbox/node-sqlite3/wiki) in the wiki.
 
 
-# INSTALLING
+# Installing
 
 You can use [`npm`](https://github.com/isaacs/npm) to download and install:
 
@@ -60,71 +67,98 @@ You can use [`npm`](https://github.com/isaacs/npm) to download and install:
 
 * GitHub's `master` branch: `npm install https://github.com/mapbox/node-sqlite3/tarball/master`
 
-In both cases the module is automatically built with npm's internal version of `node-gyp`,
-and thus your system must meet [node-gyp's requirements](https://github.com/TooTallNate/node-gyp#installation).
+The module uses [node-pre-gyp](https://github.com/mapbox/node-pre-gyp) to download a pre-compiled binary for your platform, if it exists. Otherwise, it uses `node-gyp` to build the extension.
 
 It is also possible to make your own build of `sqlite3` from its source instead of its npm package ([see below](#building-from-the-source)).
 
-It is possible to use the installed package in [node-webkit](https://github.com/rogerwang/node-webkit) instead of the vanilla Node.js, but a rebuild is required before use (see the next section).
+It is possible to use the installed package in [node-webkit](https://github.com/rogerwang/node-webkit) instead of the vanilla Node.js. See [Building for node-webkit](#building-for-node-webkit) for details.
+
+## Source install
+
+To skip searching for pre-compiled binaries, and force a build from source, use
+
+    npm install --build-from-source
+
+The sqlite3 module depends only on libsqlite3. However, by default, an internal/bundled copy of sqlite will be built and statically linked, so an externally installed sqlite3 is not required.
+
+If you wish to install against an external sqlite then you need to pass the `--sqlite` argument to `npm` wrapper:
+
+    npm install --build-from-source --sqlite=/usr/local
+
+If building against an external sqlite3 make sure to have the development headers available. Mac OS X ships with these by default. If you don't have them installed, install the `-dev` package with your package manager, e.g. `apt-get install libsqlite3-dev` for Debian/Ubuntu. Make sure that you have at least `libsqlite3` >= 3.6.
+
+Note, if building against homebrew-installed sqlite on OS X you can do:
 
+    npm install --build-from-source --sqlite=/usr/local/opt/sqlite/
 
-# REBUILDING FOR NODE-WEBKIT
+## Building for node-webkit
 
-Because of ABI differences, only a rebuilt version of `sqlite3` can be used in [node-webkit](https://github.com/rogerwang/node-webkit).
+Because of ABI differences, `sqlite3` must be built in a custom to be used with [node-webkit](https://github.com/rogerwang/node-webkit).
 
-After the `sqlite3` module is installed (according to the previous section), do the following:
+To build node-sqlite3 for node-webkit:
 
 1. Install [`nw-gyp`](https://github.com/rogerwang/nw-gyp) globally: `npm install nw-gyp -g` *(unless already installed)*
 
-2. Use `nw-gyp` to rebuild the module:
+2. Build the module with the custom flags of `--runtime`, `--target_arch`, and `--target`:
 
+```sh
+NODE_WEBKIT_VERSION="0.8.6" # see latest version at https://github.com/rogerwang/node-webkit#downloads
+npm install sqlite3 --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION)
 ```
-NODE_WEBKIT_VERSION="0.8.4" # see latest version at https://github.com/rogerwang/node-webkit#downloads
-nw-gyp rebuild --target=${NODE_WEBKIT_VERSION}
+
+This command internally calls out to [`node-pre-gyp`](https://github.com/mapbox/node-pre-gyp) which itself calls out to [`nw-gyp`](https://github.com/rogerwang/nw-gyp) when the `--runtime=node-webkit` option is passed.
+
+You can also run this command from within a `node-sqlite3` checkout:
+
+```sh
+npm install --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION)
 ```
 
 Remember the following:
 
-* In the `nw-gyp rebuild` command, specify the actual target version of your node-webkit. The command must be run in sqlite3's directory (where its `package.json` resides).
+* You must provide the right `--target_arch` flag. `ia32` is needed to target 32bit node-webkit builds, while `x64` will target 64bit node-webkit builds (if available for your platform).
 
-* After the `sqlite3` package is rebuilt for node-webkit it cannot run in the vanilla Node.js (and vice versa).
+* After the `sqlite3` package is built for node-webkit it cannot run in the vanilla Node.js (and vice versa).
    * For example, `npm test` of the node-webkit's package would fail.
-   * If you need `sqlite3` package both for Node.js and node-webkit, then you should make two separate installations of `sqlite3` (in different directories) and rebuild only one of them for node-webkit.
 
 Visit the “[Using Node modules](https://github.com/rogerwang/node-webkit/wiki/Using-Node-modules)” article in the node-webkit's wiki for more details.
 
+## Building for sqlcipher
 
-# BUILDING FROM THE SOURCE
+For instructions for building sqlcipher see
+[Building SQLCipher for node.js](https://coolaj86.com/articles/building-sqlcipher-for-node-js-on-raspberry-pi-2/)
 
-Unless building via `npm install` (which uses its own `node-gyp`) you will need `node-gyp` installed globally:
+To run node-sqlite3 against sqlcipher you need to compile from source by passing build options like:
 
-    npm install node-gyp -g
+    npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/
+    
+    node -e 'require("sqlite3")'
 
-The sqlite3 module depends only on libsqlite3. However, by default, an internal/bundled copy of sqlite will be built and statically linked, so an externally installed sqlite3 is not required.
+If your sqlcipher is installed in a custom location (if you compiled and installed it yourself),
+you'll also need to to set some environment variables:
 
-If you wish to install against an external sqlite then you need to pass the `--sqlite` argument to `node-gyp`, `npm install` or the `configure` wrapper.
+### On OS X with Homebrew
 
-    ./configure --sqlite=/usr/local
-    make
+Set the location where `brew` installed it:
 
-Or, using the node-gyp directly:
+    export LDFLAGS="-L`brew --prefix`/opt/sqlcipher/lib"
+    export CPPFLAGS="-I`brew --prefix`/opt/sqlcipher/include"
+    npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=`brew --prefix`
+    
+    node -e 'require("sqlite3")'
 
-     node-gyp --sqlite=/usr/local
-     make
+### On most Linuxes (including Raspberry Pi)
 
-Or, using npm:
+Set the location where `make` installed it:
 
-     npm install --sqlite=/usr/local
+    export LDFLAGS="-L/usr/local/lib"
+    export CPPFLAGS="-I/usr/local/include -I/usr/local/include/sqlcipher"
+    export CXXFLAGS="$CPPFLAGS"
+    npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/local --verbose
+    
+    node -e 'require("sqlite3")'
 
-If building against an external sqlite3 make sure to have the development headers available. Mac OS X ships with these by default. If you don't have them installed, install the `-dev` package with your package manager, e.g. `apt-get install libsqlite3-dev` for Debian/Ubuntu. Make sure that you have at least `libsqlite3` >= 3.6.
-
-Note, if building against homebrew-installed sqlite on OS X you can do:
-
-    ./configure --sqlite=/usr/local/opt/sqlite/
-    make
-
-
-# TESTING
+# Testing
 
 [mocha](https://github.com/visionmedia/mocha) is required to run unit tests.
 
@@ -134,8 +168,7 @@ In sqlite3's directory (where its `package.json` resides) run the following:
     npm test
 
 
-
-# CONTRIBUTORS
+# Contributors
 
 * [Konstantin Käfer](https://github.com/kkaefer)
 * [Dane Springmeyer](https://github.com/springmeyer)
@@ -152,8 +185,7 @@ In sqlite3's directory (where its `package.json` resides) run the following:
 * [Mithgol](https://github.com/Mithgol)
 
 
-
-# ACKNOWLEDGEMENTS
+# Acknowledgments
 
 Thanks to [Orlando Vazquez](https://github.com/orlandov),
 [Eric Fredricksen](https://github.com/grumdrig) and
@@ -162,6 +194,6 @@ Thanks to [Orlando Vazquez](https://github.com/orlandov),
 Development of this module is sponsored by [MapBox](http://mapbox.org/).
 
 
-# LICENSE
+# License
 
 `node-sqlite3` is [BSD licensed](https://github.com/mapbox/node-sqlite3/raw/master/LICENSE).
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..e930a96
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,56 @@
+environment:
+  node_pre_gyp_accessKeyId:
+    secure: 7DrSVc5eIGtmMcki5H+iRft+Tk3MJTwDBQEUuJHWaQ4=
+  node_pre_gyp_secretAccessKey:
+    secure: 1amwJJw9fu0j6dXnc5KsAQbSYf7Cjw/dapT6OZWABa6nc52grkKeLQ+DGaOfQz8i
+  matrix:
+    - nodejs_version: 0.10.40
+      platform: x86
+      msvs_toolset: 12
+    - nodejs_version: 0.10.40
+      platform: x64
+      msvs_toolset: 12
+    - nodejs_version: 0.12.7
+      platform: x86
+      msvs_toolset: 12
+    - nodejs_version: 0.12.7
+      platform: x64
+      msvs_toolset: 12
+    - nodejs_version: 4.0.0
+      platform: x64
+      msvs_toolset: 12
+    - nodejs_version: 4.0.0
+      platform: x86
+      msvs_toolset: 12
+    - nodejs_version: 5.0.0
+      platform: x64
+      msvs_toolset: 12
+    - nodejs_version: 5.0.0
+      platform: x86
+      msvs_toolset: 12
+    # custom visual studio 2015 builds
+    - nodejs_version: 0.10.40
+      platform: x86
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+    - nodejs_version: 0.10.40
+      platform: x64
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+    - nodejs_version: 0.12.7
+      platform: x86
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+    - nodejs_version: 0.12.7
+      platform: x64
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+
+os: Visual Studio 2015
+
+install:
+  - scripts\build-appveyor.bat
+
+build: OFF
+test: OFF
+deploy: OFF
diff --git a/binding.gyp b/binding.gyp
index 6d5babb..a0c5faa 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -2,20 +2,27 @@
   "includes": [ "deps/common-sqlite.gypi" ],
   "variables": {
       "sqlite%":"internal",
-      "module_name":"node_sqlite3",
-      "module_path":"./lib/"
+      "sqlite_libname%":"sqlite3"
   },
   "targets": [
     {
       "target_name": "<(module_name)",
+      "include_dirs": ["<!(node -e \"require('nan')\")"],
       "conditions": [
         ["sqlite != 'internal'", {
+            "include_dirs": [ "<(sqlite)/include" ],
             "libraries": [
-               "-L<@(sqlite)/lib",
-               "-lsqlite3"
+               "-l<(sqlite_libname)"
             ],
-            "include_dirs": [ "<@(sqlite)/include" ],
-            "conditions": [ [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<@(sqlite)/lib"]} ] ]
+            "conditions": [ [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<@(sqlite)/lib"]} ] ],
+            "conditions": [ [ "OS!='win'", {"libraries+":["-L<@(sqlite)/lib"]} ] ],
+            'msvs_settings': {
+              'VCLinkerTool': {
+                'AdditionalLibraryDirectories': [
+                  '<(sqlite)/lib'
+                ],
+              },
+            }
         },
         {
             "dependencies": [
@@ -24,6 +31,7 @@
         }
         ]
       ],
+      "cflags": [ "-include ../src/gcc-preinclude.h" ],
       "sources": [
         "src/database.cc",
         "src/node_sqlite3.cc",
diff --git a/configure b/configure
deleted file mode 100755
index d0184d1..0000000
--- a/configure
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-`npm explore npm -g -- pwd`/bin/node-gyp-bin/node-gyp configure $@
\ No newline at end of file
diff --git a/deps/common-sqlite.gypi b/deps/common-sqlite.gypi
index c03d747..1148aa6 100644
--- a/deps/common-sqlite.gypi
+++ b/deps/common-sqlite.gypi
@@ -1,5 +1,56 @@
 {
   'variables': {
-      'sqlite_version%':'3080200'
+      'sqlite_version%':'3090100',
+      "toolset%":'',
+  },
+  'target_defaults': {
+    'default_configuration': 'Release',
+    'msbuild_toolset':'<(toolset)',
+    'configurations': {
+      'Debug': {
+        'defines!': [
+          'NDEBUG'
+        ],
+        'cflags_cc!': [
+          '-O3',
+          '-Os',
+          '-DNDEBUG'
+        ],
+        'xcode_settings': {
+          'OTHER_CPLUSPLUSFLAGS!': [
+            '-O3',
+            '-Os',
+            '-DDEBUG'
+          ],
+          'GCC_OPTIMIZATION_LEVEL': '0',
+          'GCC_GENERATE_DEBUGGING_SYMBOLS': 'YES'
+        },
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'ExceptionHandling': 1, # /EHsc
+          }
+        }
+      },
+      'Release': {
+        'defines': [
+          'NDEBUG'
+        ],
+        'xcode_settings': {
+          'OTHER_CPLUSPLUSFLAGS!': [
+            '-Os',
+            '-O2'
+          ],
+          'GCC_OPTIMIZATION_LEVEL': '3',
+          'GCC_GENERATE_DEBUGGING_SYMBOLS': 'NO',
+          'DEAD_CODE_STRIPPING': 'YES',
+          'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES'
+        },
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'ExceptionHandling': 1, # /EHsc
+          }
+        }
+      }
+    }
   }
-}
\ No newline at end of file
+}
diff --git a/deps/sqlite3.gyp b/deps/sqlite3.gyp
index 9d7e9fc..45a6423 100755
--- a/deps/sqlite3.gyp
+++ b/deps/sqlite3.gyp
@@ -1,7 +1,10 @@
 {
   'includes': [ 'common-sqlite.gypi' ],
   'target_defaults': {
-    'default_configuration': 'Debug',
+    'default_configuration': 'Release',
+    'cflags':[
+      '-std=c99'
+    ],
     'configurations': {
       'Debug': {
         'defines': [ 'DEBUG', '_DEBUG' ],
@@ -68,6 +71,7 @@
       'dependencies': [
         'action_before_build'
       ],
+      'cflags': [ '-include ../src/gcc-preinclude.h' ],
       'sources': [
         '<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/sqlite3.c'
       ],
@@ -76,6 +80,7 @@
         'defines': [
           'SQLITE_THREADSAFE=1',
           'SQLITE_ENABLE_FTS3',
+          'SQLITE_ENABLE_JSON1',
           'SQLITE_ENABLE_RTREE'
         ],
       },
@@ -87,6 +92,7 @@
         '_REENTRANT=1',
         'SQLITE_THREADSAFE=1',
         'SQLITE_ENABLE_FTS3',
+        'SQLITE_ENABLE_JSON1',
         'SQLITE_ENABLE_RTREE'
       ],
       'export_dependent_settings': [
diff --git a/lib/binary_name.js b/lib/binary_name.js
deleted file mode 100644
index 84a63c6..0000000
--- a/lib/binary_name.js
+++ /dev/null
@@ -1,59 +0,0 @@
-
-var path = require('path');
-
-var Binary = function(options) {
-  var options = options || {};
-  var package_json = options.package_json || require('../package.json');
-  this.name = options.name || 'binding';
-  this.configuration = options.configuration || 'Release';
-  this.uri = options.uri || 'http://'+this.name+'.s3.amazonaws.com/';
-  this.module_maj_min = package_json.version.split('.').slice(0,2).join('.');
-  this.module_abi = package_json.abi;
-  this.platform = options.platform || process.platform;
-  this.target_arch = options.target_arch || process.arch;
-  if (process.versions.modules) {
-    // added in >= v0.10.4 and v0.11.7
-    // https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e
-    this.node_abi = 'node-v' + (+process.versions.modules);
-  } else {
-    this.node_abi = 'v8-' + process.versions.v8.split('.').slice(0,2).join('.');
-  }
-}
-
-Binary.prototype.filename = function() {
-    return this.name + '.node';
-}
-
-Binary.prototype.compression = function() {
-    return '.tar.gz';
-}
-
-Binary.prototype.getBasePath = function() {
-    return this.node_abi
-           + '-' + this.platform
-           + '-' + this.target_arch;
-}
-
-Binary.prototype.getRequirePath = function(configuration) {
-    return './' + path.join('binding',
-        configuration || this.configuration,
-        this.getBasePath(),
-        this.filename());
-}
-
-Binary.prototype.getModuleAbi = function() {
-    return this.name + '-v' + this.module_maj_min + '.' + this.module_abi;
-}
-
-Binary.prototype.getArchivePath = function() {
-    return this.getModuleAbi()
-           + '-'
-           + this.getBasePath()
-           + this.compression();
-}
-
-Binary.prototype.getRemotePath = function() {
-    return this.uri+this.configuration+'/'+this.getArchivePath();
-}
-
-module.exports.Binary = Binary;
\ No newline at end of file
diff --git a/lib/sqlite3.js b/lib/sqlite3.js
index f0d35a4..466b902 100644
--- a/lib/sqlite3.js
+++ b/lib/sqlite3.js
@@ -1,13 +1,24 @@
-var binding = require('./node_sqlite3.node');
-var sqlite3 = module.exports = exports = binding;
+var binary = require('node-pre-gyp');
 var path = require('path');
-var util = require('util');
+var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
+var binding = require(binding_path);
+var sqlite3 = module.exports = exports = binding;
 var EventEmitter = require('events').EventEmitter;
 
-function errorCallback(args) {
-    if (typeof args[args.length - 1] === 'function') {
-        var callback = args[args.length - 1];
-        return function(err) { if (err) callback(err); };
+function normalizeMethod (fn) {
+    return function (sql) {
+        var errBack;
+        var args = Array.prototype.slice.call(arguments, 1);
+        if (typeof args[args.length - 1] === 'function') {
+            var callback = args[args.length - 1];
+            errBack = function(err) {
+                if (err) {
+                    callback(err);
+                }
+            };
+        }
+        var statement = new Statement(this, sql, errBack);
+        return fn.call(this, statement, args);
     }
 }
 
@@ -23,9 +34,7 @@ sqlite3.cached = {
             return new Database(file, a, b);
         }
 
-        if (file[0] !== '/') {
-            file = path.join(process.cwd(), file);
-        }
+        file = path.resolve(file);
 
         if (!sqlite3.cached.objects[file]) {
             var db =sqlite3.cached.objects[file] = new Database(file, a, b);
@@ -54,56 +63,40 @@ inherits(Database, EventEmitter);
 inherits(Statement, EventEmitter);
 
 // Database#prepare(sql, [bind1, bind2, ...], [callback])
-Database.prototype.prepare = function(sql) {
-    var params = Array.prototype.slice.call(arguments, 1);
-
-    if (!params.length || (params.length === 1 && typeof params[0] === 'function')) {
-        return new Statement(this, sql, params[0]);
-    }
-    else {
-        var statement = new Statement(this, sql, errorCallback(params));
-        return statement.bind.apply(statement, params);
-    }
-};
+Database.prototype.prepare = normalizeMethod(function(statement, params) {
+    return params.length
+        ? statement.bind.apply(statement, params)
+        : statement;
+});
 
 // Database#run(sql, [bind1, bind2, ...], [callback])
-Database.prototype.run = function(sql) {
-    var params = Array.prototype.slice.call(arguments, 1);
-    var statement = new Statement(this, sql, errorCallback(params));
+Database.prototype.run = normalizeMethod(function(statement, params) {
     statement.run.apply(statement, params).finalize();
     return this;
-};
+});
 
 // Database#get(sql, [bind1, bind2, ...], [callback])
-Database.prototype.get = function(sql) {
-    var params = Array.prototype.slice.call(arguments, 1);
-    var statement = new Statement(this, sql, errorCallback(params));
+Database.prototype.get = normalizeMethod(function(statement, params) {
     statement.get.apply(statement, params).finalize();
     return this;
-};
+});
 
 // Database#all(sql, [bind1, bind2, ...], [callback])
-Database.prototype.all = function(sql) {
-    var params = Array.prototype.slice.call(arguments, 1);
-    var statement = new Statement(this, sql, errorCallback(params));
+Database.prototype.all = normalizeMethod(function(statement, params) {
     statement.all.apply(statement, params).finalize();
     return this;
-};
+});
 
 // Database#each(sql, [bind1, bind2, ...], [callback], [complete])
-Database.prototype.each = function(sql) {
-    var params = Array.prototype.slice.call(arguments, 1);
-    var statement = new Statement(this, sql, errorCallback(params));
+Database.prototype.each = normalizeMethod(function(statement, params) {
     statement.each.apply(statement, params).finalize();
     return this;
-};
+});
 
-Database.prototype.map = function(sql) {
-    var params = Array.prototype.slice.call(arguments, 1);
-    var statement = new Statement(this, sql, errorCallback(params));
+Database.prototype.map = normalizeMethod(function(statement, params) {
     statement.map.apply(statement, params).finalize();
     return this;
-};
+});
 
 Statement.prototype.map = function() {
     var params = Array.prototype.slice.call(arguments);
@@ -163,22 +156,30 @@ Database.prototype.removeAllListeners = function(type) {
 sqlite3.verbose = function() {
     if (!isVerbose) {
         var trace = require('./trace');
-        trace.extendTrace(Database.prototype, 'prepare');
-        trace.extendTrace(Database.prototype, 'get');
-        trace.extendTrace(Database.prototype, 'run');
-        trace.extendTrace(Database.prototype, 'all');
-        trace.extendTrace(Database.prototype, 'each');
-        trace.extendTrace(Database.prototype, 'map');
-        trace.extendTrace(Database.prototype, 'exec');
-        trace.extendTrace(Database.prototype, 'close');
-        trace.extendTrace(Statement.prototype, 'bind');
-        trace.extendTrace(Statement.prototype, 'get');
-        trace.extendTrace(Statement.prototype, 'run');
-        trace.extendTrace(Statement.prototype, 'all');
-        trace.extendTrace(Statement.prototype, 'each');
-        trace.extendTrace(Statement.prototype, 'map');
-        trace.extendTrace(Statement.prototype, 'reset');
-        trace.extendTrace(Statement.prototype, 'finalize');
+        [
+            'prepare',
+            'get',
+            'run',
+            'all',
+            'each',
+            'map',
+            'close',
+            'exec'
+        ].forEach(function (name) {
+            trace.extendTrace(Database.prototype, name);
+        });
+        [
+            'bind',
+            'get',
+            'run',
+            'all',
+            'each',
+            'map',
+            'reset',
+            'finalize',
+        ].forEach(function (name) {
+            trace.extendTrace(Statement.prototype, name);
+        });
         isVerbose = true;
     }
 
diff --git a/package.json b/package.json
index c6ed882..dc226b3 100644
--- a/package.json
+++ b/package.json
@@ -1,17 +1,18 @@
 {
     "name": "sqlite3",
     "description": "Asynchronous, non-blocking SQLite3 bindings",
-    "version": "2.2.0",
+    "version": "3.1.3",
     "homepage": "http://github.com/mapbox/node-sqlite3",
     "author": {
         "name": "MapBox",
         "url": "https://mapbox.com/"
     },
     "binary": {
-        "module_name": "node_sqlite3",
-        "module_path": "./lib",
-        "remote_uri": "http://node-sqlite3.s3.amazonaws.com",
-        "template": "{configuration}/{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz"
+        "module_name" : "node_sqlite3",
+        "module_path" : "./lib/binding/{node_abi}-{platform}-{arch}",
+        "host"        : "https://mapbox-node-binary.s3.amazonaws.com",
+        "remote_path" : "./{name}/v{version}/{toolset}/",
+        "package_name": "{node_abi}-{platform}-{arch}.tar.gz"
     },
     "contributors": [
         "Konstantin Käfer <mail at kkaefer.com>",
@@ -28,30 +29,36 @@
         "Johannes Schauer <josch at pyneo.org>",
         "Nathan Rajlich <nathan at tootallnate.net>",
         "AJ ONeal <coolaj86 at gmail.com>",
-        "Mithgol"
+        "Mithgol",
+        "Ben Noordhuis <ben at strongloop.com>"
     ],
     "repository": {
         "type": "git",
         "url": "git://github.com/mapbox/node-sqlite3.git"
     },
     "dependencies": {
-        "node-pre-gyp": "~0.2.5"
+        "nan": "~2.2.0",
+        "node-pre-gyp": "~0.6.25"
     },
     "bundledDependencies": [
         "node-pre-gyp"
     ],
-    "engines": {
-        "node": ">= 0.8.0 < 0.11.0"
+    "devDependencies": {
+        "mocha": "~2.3.3",
+        "aws-sdk": "~2.1.26"
     },
     "scripts": {
+        "prepublish":"npm ls",
         "install": "node-pre-gyp install --fallback-to-build",
         "pretest": "node test/support/createdb.js",
-        "test": "mocha -R spec --timeout 200000"
+        "test": "mocha -R spec --timeout 480000"
     },
-    "licenses": [
-        {
-            "type": "BSD"
-        }
+    "license": "BSD-3-Clause",
+    "keywords": [
+        "sql",
+        "sqlite",
+        "sqlite3",
+        "database"
     ],
     "main": "./lib/sqlite3"
-}
\ No newline at end of file
+}
diff --git a/scripts/build-appveyor.bat b/scripts/build-appveyor.bat
new file mode 100644
index 0000000..bbe7473
--- /dev/null
+++ b/scripts/build-appveyor.bat
@@ -0,0 +1,160 @@
+ at ECHO OFF
+SETLOCAL
+SET EL=0
+
+ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SET PATH=%CD%;%PATH%
+SET msvs_version=2013
+IF "%msvs_toolset"=="14" SET msvs_version=2015
+
+ECHO APPVEYOR^: %APPVEYOR%
+ECHO nodejs_version^: %nodejs_version%
+ECHO platform^: %platform%
+ECHO msvs_toolset^: %msvs_toolset%
+ECHO msvs_version^: %msvs_version%
+ECHO TOOLSET_ARGS^: %TOOLSET_ARGS%
+
+
+ECHO activating VS command prompt
+:: NOTE this call makes the x64 -> X64
+IF /I "%platform%"=="x64" ECHO x64 && CALL "C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\vcvarsall.bat" amd64
+IF /I "%platform%"=="x86" ECHO x86 && CALL "C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\vcvarsall.bat" x86
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO using compiler^: && CALL cl
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO using MSBuild^: && CALL msbuild /version && ECHO.
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+
+ECHO downloading/installing node
+::only use Install-Product when using VS2013
+::IF /I "%APPVEYOR%"=="True" IF /I "%msvs_toolset%"=="12" powershell Install-Product node $env:nodejs_version $env:Platform
+::TESTING:
+::always install (get npm matching node), but delete installed programfiles node.exe afterwards for VS2015 (using custom node.exe)
+IF /I "%APPVEYOR%"=="True" GOTO APPVEYOR_INSTALL
+GOTO SKIP_APPVEYOR_INSTALL
+
+:APPVEYOR_INSTALL
+IF /I "%platform%"=="x64" powershell Install-Product node $env:nodejs_version x64
+IF /I "%platform%"=="x86" powershell Install-Product node $env:nodejs_version x86
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+:SKIP_APPVEYOR_INSTALL
+IF /I "%msvs_toolset%"=="12" GOTO NODE_INSTALLED
+
+
+::custom node for VS2015
+SET ARCHPATH=
+IF "%platform%"=="X64" (SET ARCHPATH=x64/)
+IF "%platform%"=="x64" (SET ARCHPATH=x64/)
+SET NODE_URL=https://mapbox.s3.amazonaws.com/node-cpp11/v%nodejs_version%/%ARCHPATH%node.exe
+ECHO downloading node^: %NODE_URL%
+powershell Invoke-WebRequest "${env:NODE_URL}" -OutFile node.exe
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO deleting node ...
+SET NODE_EXE_PRG=%ProgramFiles%\nodejs\node.exe
+IF EXIST "%NODE_EXE_PRG%" ECHO found %NODE_EXE_PRG%, deleting... && DEL /F "%NODE_EXE_PRG%"
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+SET NODE_EXE_PRG=%ProgramFiles(x86)%\nodejs\node.exe
+IF EXIST "%NODE_EXE_PRG%" ECHO found %NODE_EXE_PRG%, deleting... && DEL /F "%NODE_EXE_PRG%"
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+
+:NODE_INSTALLED
+
+ECHO available node.exe^:
+call where node
+ECHO available npm^:
+call where npm
+
+ECHO node^: && call node -v
+call node -e "console.log(process.argv,process.execPath)"
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO npm^: && CALL npm -v
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO ===== where npm puts stuff START ============
+ECHO npm root && CALL npm root
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+ECHO npm root -g && CALL npm root -g
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO npm bin && CALL npm bin
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+ECHO npm bin -g && CALL npm bin -g
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+SET NPM_BIN_DIR=
+FOR /F "tokens=*" %%i in ('CALL npm bin -g') DO SET NPM_BIN_DIR=%%i
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+IF /I "%NPM_BIN_DIR%"=="%CD%" ECHO ERROR npm bin -g equals local directory && SET ERRORLEVEL=1 && GOTO ERROR
+ECHO ===== where npm puts stuff END ============
+
+
+ECHO installing node-gyp
+CALL npm install -g node-gyp
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+CALL npm install --build-from-source --msvs_version=%msvs_version% %TOOLSET_ARGS% --loglevel=http
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+FOR /F "tokens=*" %%i in ('CALL node_modules\.bin\node-pre-gyp reveal module --silent') DO SET MODULE=%%i
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+FOR /F "tokens=*" %%i in ('node -e "console.log(process.execPath)"') DO SET NODE_EXE=%%i
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+dumpbin /DEPENDENTS "%NODE_EXE%"
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+dumpbin /DEPENDENTS "%MODULE%"
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+
+::skipping check for errorlevel npm test result when using io.js
+::@springmeyer: how to proceed?
+IF NOT "%nodejs_version%"=="1.8.1" IF NOT "%nodejs_version%"=="2.0.0" GOTO CHECK_NPM_TEST_ERRORLEVEL
+
+ECHO calling npm test
+CALL npm test
+ECHO ==========================================
+ECHO ==========================================
+ECHO ==========================================
+ECHO using iojs, not checking test result!!!!!!!!!
+ECHO ==========================================
+ECHO ==========================================
+ECHO ==========================================
+
+GOTO NPM_TEST_FINISHED
+
+
+:CHECK_NPM_TEST_ERRORLEVEL
+ECHO calling npm test
+CALL npm test
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+:NPM_TEST_FINISHED
+
+
+CALL node_modules\.bin\node-pre-gyp package %TOOLSET_ARGS%
+::make commit message env var shorter
+SET CM=%APPVEYOR_REPO_COMMIT_MESSAGE%
+IF NOT "%CM%" == "%CM:[publish binary]=%" (ECHO publishing && CALL node_modules\.bin\node-pre-gyp --msvs_version=%msvs_version% publish %TOOLSET_ARGS%) ELSE (ECHO not publishing)
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+GOTO DONE
+
+
+
+:ERROR
+ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ECHO ERRORLEVEL^: %ERRORLEVEL%
+SET EL=%ERRORLEVEL%
+
+:DONE
+ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+EXIT /b %EL%
diff --git a/scripts/build-local.bat b/scripts/build-local.bat
new file mode 100644
index 0000000..6c7e269
--- /dev/null
+++ b/scripts/build-local.bat
@@ -0,0 +1,59 @@
+ at ECHO OFF
+SETLOCAL
+SET EL=0
+
+ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SET PATH=C:\Python27;%PATH%
+
+SET APPVEYOR_REPO_COMMIT_MESSAGE=local build
+
+IF EXIST lib\binding ECHO deleting lib/binding && RD /Q /S lib\binding
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+IF EXIST node_modules ECHO deleting node_modules && RD /Q /S node_modules
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO                 ============================
+ECHO                           VS2013
+ECHO                 ============================
+SET nodejs_version=0.10.36
+SET platform=x64
+SET msvs_toolset=12
+SET TOOLSET_ARGS=
+
+CALL scripts\build-appveyor.bat
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+
+
+
+IF EXIST lib\binding ECHO deleting lib/binding && RD /Q /S lib\binding
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+IF EXIST node_modules ECHO deleting node_modules && RD /Q /S node_modules
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+ECHO                 ============================
+ECHO                           VS2015
+ECHO                 ============================
+SET nodejs_version=0.12.7
+SET platform=x86
+SET msvs_toolset=14
+SET TOOLSET_ARGS=--dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+
+CALL scripts\build-appveyor.bat
+IF %ERRORLEVEL% NEQ 0 GOTO ERROR
+
+
+
+
+GOTO DONE
+
+:ERROR
+ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ECHO ERRORLEVEL^: %ERRORLEVEL%
+SET EL=%ERRORLEVEL%
+
+:DONE
+ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+EXIT /b %EL%
diff --git a/scripts/build.bat b/scripts/build.bat
deleted file mode 100644
index 9263a27..0000000
--- a/scripts/build.bat
+++ /dev/null
@@ -1,49 +0,0 @@
- at rem setup
- at rem git clone git://github.com/marcelklehr/nodist.git
- at rem create ~/.node_pre_gyprc
- at rem note, for 64 builds you may need to win7 sdk terminal
- at rem https://github.com/TooTallNate/node-gyp/issues/112
-set PATH=c:\dev2\nodist\bin;%PATH%
-set PATH=node_modules\.bin;%PATH%
-set PATH=%PATH%;c:\Python27
-
- at rem 32 bit
-set NODIST_X64=0
-nodist use stable
-node -e "console.log(process.version + ' ' + process.arch)"
-node-pre-gyp clean
-npm install --build-from-source
-npm test
-node-pre-gyp package publish
-node-pre-gyp clean
-
- at rem 64 bit
-@ rem cannot open input file 'kernel32.lib' http://www.microsoft.com/en-us/download/details.aspx?id=4422
-set NODIST_X64=1
-nodist use stable
-node -e "console.log(process.version + ' ' + process.arch)"
-node-pre-gyp clean
-npm install --build-from-source
-npm test
-node-pre-gyp package publish
-node-pre-gyp clean
-
-@ rem 32 bit v0.8x
-set NODIST_X64=0
-nodist use v0.8
-node -e "console.log(process.version + ' ' + process.arch)"
-node-pre-gyp clean
-npm install --build-from-source
-npm test
-node-pre-gyp package publish
-node-pre-gyp clean
-
- at rem 64 bit v0.8.x
-set NODIST_X64=1
-nodist use v0.8
-node -e "console.log(process.version + ' ' + process.arch)"
-node-pre-gyp clean
-npm install --build-from-source
-npm test
-node-pre-gyp package publish
-node-pre-gyp clean
diff --git a/scripts/build_against_node.sh b/scripts/build_against_node.sh
new file mode 100755
index 0000000..2982740
--- /dev/null
+++ b/scripts/build_against_node.sh
@@ -0,0 +1,79 @@
+#!/usr/bin/env bash
+
+source ~/.nvm/nvm.sh
+
+set -e -u
+
+function publish() {
+    if [[ ${PUBLISHABLE:-false} == true ]] && [[ ${COMMIT_MESSAGE} =~ "[publish binary]" ]]; then
+        node-pre-gyp package testpackage
+        node-pre-gyp publish
+        node-pre-gyp info
+        make clean
+    fi
+}
+
+# test installing from source
+if [[ ${COVERAGE} == true ]]; then
+    CXXFLAGS="--coverage" LDFLAGS="--coverage" npm install --build-from-source  --clang=1
+    npm test
+    ./py-local/bin/cpp-coveralls --exclude node_modules --exclude tests --build-root build --gcov-options '\-lp' --exclude docs --exclude build/Release/obj/gen --exclude deps  > /dev/null
+else
+    npm install --build-from-source  --clang=1
+    npm test
+fi
+
+
+publish
+
+# now test building against shared sqlite
+export NODE_SQLITE3_JSON1=no
+if [[ $(uname -s) == 'Darwin' ]]; then
+    brew install sqlite
+    npm install --build-from-source --sqlite=$(brew --prefix) --clang=1
+else
+    npm install --build-from-source --sqlite=/usr --clang=1
+fi
+npm test
+export NODE_SQLITE3_JSON1=yes
+
+platform=$(uname -s | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/")
+
+: '
+if [[ $(uname -s) == 'Linux' ]]; then
+    # node v0.8 and above provide pre-built 32 bit and 64 bit binaries
+    # so here we use the 32 bit ones to also test 32 bit builds
+    NVER=`node -v`
+    # enable 32 bit node
+    export PATH=$(pwd)/node-${NVER}-${platform}-x86/bin:$PATH
+    if [[ ${NODE_VERSION:0:4} == 'iojs' ]]; then
+        wget https://iojs.org/download/release/${NVER}/iojs-${NVER}-${platform}-x86.tar.gz
+        tar xf iojs-${NVER}-${platform}-x86.tar.gz
+        # enable 32 bit iojs
+        export PATH=$(pwd)/iojs-${NVER}-${platform}-x86/bin:$(pwd)/iojs-${NVER}-${platform}-ia32/bin:$PATH
+    else
+        wget http://nodejs.org/dist/${NVER}/node-${NVER}-${platform}-x86.tar.gz
+        tar xf node-${NVER}-${platform}-x86.tar.gz
+        # enable 32 bit node
+        export PATH=$(pwd)/node-${NVER}-${platform}-x86/bin:$(pwd)/node-${NVER}-${platform}-ia32/bin:$PATH
+    fi
+    which node
+    ls -l $(which node)
+    #node -e "console.log(process.arch,process.execPath)"
+    # install 32 bit compiler toolchain and X11
+    # test source compile in 32 bit mode with internal libsqlite3
+    CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source  --clang=1
+    node-pre-gyp package testpackage
+    npm test
+    publish
+    make clean
+    # broken for some unknown reason against io.js
+    if [[ ${NODE_VERSION:0:4} != 'iojs' ]]; then
+        # test source compile in 32 bit mode against external libsqlite3
+        export NODE_SQLITE3_JSON1=no
+        CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source --sqlite=/usr  --clang=1
+        npm test
+    fi
+fi
+
+'
diff --git a/scripts/build_against_node_webkit.sh b/scripts/build_against_node_webkit.sh
new file mode 100755
index 0000000..94706b4
--- /dev/null
+++ b/scripts/build_against_node_webkit.sh
@@ -0,0 +1,91 @@
+#!/usr/bin/env bash
+
+
+if [[ ! -d ../.nvm ]]; then
+    git clone https://github.com/creationix/nvm.git ../.nvm
+fi
+source ../.nvm/nvm.sh
+nvm install 0.10
+
+set -u -e
+
+npm install nw-gyp -g
+
+OLD_PATH="$PATH"
+
+GYP_ARGS="--runtime=node-webkit --target=${NODE_WEBKIT} --target_arch=${TARGET_ARCH}"
+if [[ $(uname -s) == 'Darwin' ]]; then
+    if [[ '${TARGET_ARCH}' == 'x64' ]]; then
+       # do not build on Mac OS X x64 until node-webkit 0.10.1 is released
+       false
+    fi
+fi
+
+if [[ $(uname -s) == 'Darwin' ]]; then
+    export NW_DOWNLOAD=node-webkit-v${NODE_WEBKIT}-osx-${TARGET_ARCH}
+    wget http://dl.node-webkit.org/v${NODE_WEBKIT}/${NW_DOWNLOAD}.zip
+    unzip -q ${NW_DOWNLOAD}.zip
+    export PATH=$(pwd)/node-webkit.app/Contents/MacOS/:${PATH}
+    # v0.10.0-rc1 unzips with extra folder
+    export PATH=$(pwd)/${NW_DOWNLOAD}/node-webkit.app/Contents/MacOS/:${PATH}
+    npm install --build-from-source ${GYP_ARGS}
+else
+    sudo apt-get install build-essential
+    # Linux
+    export NW_DOWNLOAD=node-webkit-v${NODE_WEBKIT}-linux-${TARGET_ARCH}
+    # for testing node-webkit, launch a virtual display
+    export DISPLAY=:99.0
+    # NOTE: travis already has xvfb installed
+    # http://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-GUI-%28e.g.-a-Web-browser%29
+    sh -e /etc/init.d/xvfb start +extension RANDR
+    wget http://dl.node-webkit.org/v${NODE_WEBKIT}/${NW_DOWNLOAD}.tar.gz
+    tar xf ${NW_DOWNLOAD}.tar.gz
+    export PATH=$(pwd)/${NW_DOWNLOAD}:${PATH}
+    if [[ "${TARGET_ARCH}" == 'ia32' ]]; then
+        # for nw >= 0.11.0 on ia32 we need gcc/g++ 4.8
+        IFS='.' read -a NODE_WEBKIT_VERSION <<< "${NODE_WEBKIT}"
+        if test ${NODE_WEBKIT_VERSION[0]} -ge 0 -a ${NODE_WEBKIT_VERSION[1]} -ge 11; then
+            # travis-ci runs ubuntu 12.04, so we need this ppa for gcc/g++ 4.8
+            sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
+            export CC=gcc-4.8
+            export CXX=g++-4.8
+            export CXXFLAGS="-fpermissive"
+            COMPILER_PACKAGES="gcc-4.8-multilib g++-4.8-multilib"
+        else
+            export CC=gcc-4.6
+            export CXX=g++-4.6
+            export CXXFLAGS="-fpermissive"
+            COMPILER_PACKAGES="gcc-multilib g++-multilib"
+        fi
+        # need to update to avoid 404 for linux-libc-dev_3.2.0-64.97_amd64.deb
+        sudo apt-get update
+        # prepare packages for 32-bit builds on Linux
+        sudo apt-get -y install $COMPILER_PACKAGES libx11-6:i386 libnotify4:i386 libxtst6:i386 libcap2:i386 libglib2.0-0:i386 libgtk2.0-0:i386 libatk1.0-0:i386 libgdk-pixbuf2.0-0:i386 libcairo2:i386 libfreetype6:i386 libfontconfig1:i386 libxcomposite1:i386 libasound2:i386 libxdamage1:i386 libxext6:i386 libxfixes3:i386 libnss3:i386 libnspr4:i386 libgconf-2-4:i386 libexpat1:i386 libdbus-1-3:i386 libudev0:i386
+        # also use ldd to find out if some necessary apt-get is missing
+        ldd $(pwd)/${NW_DOWNLOAD}/nw
+        npm install --build-from-source ${GYP_ARGS}
+    else
+        npm install --build-from-source ${GYP_ARGS}
+    fi
+fi
+
+# test the package
+node-pre-gyp package testpackage ${GYP_ARGS}
+
+PUBLISH_BINARY=false
+if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then
+    node-pre-gyp publish ${GYP_ARGS}
+    node-pre-gyp info ${GYP_ARGS}
+    node-pre-gyp clean ${GYP_ARGS}
+    make clean
+    # now install from binary
+    INSTALL_RESULT=$(npm install ${GYP_ARGS} --fallback-to-build=false > /dev/null)$? || true
+    # if install returned non zero (errored) then we first unpublish and then call false so travis will bail at this line
+    if [[ $INSTALL_RESULT != 0 ]]; then echo "returned $INSTALL_RESULT";node-pre-gyp unpublish ${GYP_ARGS};false; fi
+    # If success then we arrive here so lets clean up
+    node-pre-gyp clean ${GYP_ARGS}
+fi
+
+# restore PATH
+export PATH="$OLD_PATH"
+rm -rf ${NW_DOWNLOAD}
diff --git a/scripts/build_for_node_webkit.cmd b/scripts/build_for_node_webkit.cmd
new file mode 100644
index 0000000..2a0878f
--- /dev/null
+++ b/scripts/build_for_node_webkit.cmd
@@ -0,0 +1,15 @@
+echo Platform: %1
+echo The list of environment variables:
+set
+if not "%1" == "x86" goto end
+if "%nw_version%" == "" goto end
+call npm install nw-gyp
+call cinst wget 7zip.commandline
+call wget http://dl.node-webkit.org/v%nw_version%/node-webkit-v%nw_version%-win-ia32.zip
+call 7z e -onw node-webkit-v%nw_version%-win-ia32.zip
+dir nw
+set PATH=nw;%PATH%
+call node-pre-gyp rebuild --runtime=node-webkit --target=%nw_version% --target_arch=ia32
+call node-pre-gyp package testpackage --runtime=node-webkit --target=%nw_version% --target_arch=ia32
+if not "%CM%" == "%CM:[publish binary]=%" call node-pre-gyp publish --msvs_version=2013 --runtime=node-webkit --target=%nw_version% --target_arch=ia32
+:end
\ No newline at end of file
diff --git a/scripts/install_node.sh b/scripts/install_node.sh
new file mode 100755
index 0000000..d534f77
--- /dev/null
+++ b/scripts/install_node.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+if [[ ${1:-false} == 'false' ]]; then
+    echo "Error: pass node version as first argument"
+    exit 1
+fi
+
+NODE_VERSION=$1
+
+# if an existing nvm is already installed we need to unload it
+nvm unload || true
+
+# here we set up the node version on the fly based on the matrix value.
+# This is done manually so that the build works the same on OS X
+rm -rf ./__nvm/ && git clone --depth 1 https://github.com/creationix/nvm.git ./__nvm
+source ./__nvm/nvm.sh
+nvm install ${NODE_VERSION}
+nvm use ${NODE_VERSION}
+node --version
+npm --version
+which node
\ No newline at end of file
diff --git a/scripts/validate_tag.sh b/scripts/validate_tag.sh
new file mode 100755
index 0000000..67d039b
--- /dev/null
+++ b/scripts/validate_tag.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -u
+
+# let's catch the case where we tag but
+# forget to increment the package.json version
+
+# check if we are on a tag
+if [ `git describe --tags --always HEAD` ]; then
+    echo 'looks like we are on a tag'
+    if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]]; then
+        echo 'git reports the same tag as travis'
+        # now check to make sure package.json `version` matches
+        MODULE_VERSION=$(node -e "console.log(require('./package.json').version)")
+        if [[ $MODULE_VERSION != $TRAVIS_BRANCH ]] && [[ v$MODULE_VERSION != $TRAVIS_BRANCH ]]; then
+            echo "package.json version ($MODULE_VERSION) does not match tag ($TRAVIS_BRANCH)"
+            exit 1
+        else
+            echo "Validation success: package.json ($MODULE_VERSION) matches tag ($TRAVIS_BRANCH)"
+        fi
+    else
+        echo "warning: travis thinks the tag ($TRAVIS_BRANCH) differs from git (`git describe --tags --always HEAD`)"
+    fi
+fi
diff --git a/src/async.h b/src/async.h
index 37b4248..2b167ce 100644
--- a/src/async.h
+++ b/src/async.h
@@ -26,7 +26,7 @@ public:
         : callback(cb_), parent(parent_) {
         watcher.data = this;
         NODE_SQLITE3_MUTEX_INIT
-        uv_async_init(uv_default_loop(), &watcher, listener);
+        uv_async_init(uv_default_loop(), &watcher, reinterpret_cast<uv_async_cb>(listener));
     }
 
     static void listener(uv_async_t* handle, int status) {
diff --git a/src/database.cc b/src/database.cc
index 50206e6..5f1e197 100644
--- a/src/database.cc
+++ b/src/database.cc
@@ -1,5 +1,4 @@
 #include <string.h>
-#include <node.h>
 
 #include "macros.h"
 #include "database.h"
@@ -7,42 +6,46 @@
 
 using namespace node_sqlite3;
 
-Persistent<FunctionTemplate> Database::constructor_template;
+Nan::Persistent<FunctionTemplate> Database::constructor_template;
 
-void Database::Init(Handle<Object> target) {
-    HandleScope scope;
+NAN_MODULE_INIT(Database::Init) {
+    Nan::HandleScope scope;
 
-    Local<FunctionTemplate> t = FunctionTemplate::New(New);
+    Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
 
-    constructor_template = Persistent<FunctionTemplate>::New(t);
-    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
-    constructor_template->SetClassName(String::NewSymbol("Database"));
+    t->InstanceTemplate()->SetInternalFieldCount(1);
+    t->SetClassName(Nan::New("Database").ToLocalChecked());
 
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", Close);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "exec", Exec);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "wait", Wait);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "loadExtension", LoadExtension);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "serialize", Serialize);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "parallelize", Parallelize);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "configure", Configure);
+    Nan::SetPrototypeMethod(t, "close", Close);
+    Nan::SetPrototypeMethod(t, "exec", Exec);
+    Nan::SetPrototypeMethod(t, "wait", Wait);
+    Nan::SetPrototypeMethod(t, "loadExtension", LoadExtension);
+    Nan::SetPrototypeMethod(t, "serialize", Serialize);
+    Nan::SetPrototypeMethod(t, "parallelize", Parallelize);
+    Nan::SetPrototypeMethod(t, "configure", Configure);
 
-    NODE_SET_GETTER(constructor_template, "open", OpenGetter);
+    NODE_SET_GETTER(t, "open", OpenGetter);
 
-    target->Set(String::NewSymbol("Database"),
-        constructor_template->GetFunction());
+    constructor_template.Reset(t);
+
+    Nan::Set(target, Nan::New("Database").ToLocalChecked(),
+        Nan::GetFunction(t).ToLocalChecked());
 }
 
 void Database::Process() {
+    Nan::HandleScope scope;
+
     if (!open && locked && !queue.empty()) {
-        EXCEPTION(String::New("Database handle is closed"), SQLITE_MISUSE, exception);
+        EXCEPTION(Nan::New("Database handle is closed").ToLocalChecked(), SQLITE_MISUSE, exception);
         Local<Value> argv[] = { exception };
         bool called = false;
 
         // Call all callbacks with the error object.
         while (!queue.empty()) {
             Call* call = queue.front();
-            if (!call->baton->callback.IsEmpty() && call->baton->callback->IsFunction()) {
-                TRY_CATCH_CALL(handle_, call->baton->callback, 1, argv);
+            Local<Function> cb = Nan::New(call->baton->callback);
+            if (!cb.IsEmpty() && cb->IsFunction()) {
+                TRY_CATCH_CALL(this->handle(), cb, 1, argv);
                 called = true;
             }
             queue.pop();
@@ -55,8 +58,8 @@ void Database::Process() {
         // When we couldn't call a callback function, emit an error on the
         // Database object.
         if (!called) {
-            Local<Value> args[] = { String::NewSymbol("error"), exception };
-            EMIT_EVENT(handle_, 2, args);
+            Local<Value> info[] = { Nan::New("error").ToLocalChecked(), exception };
+            EMIT_EVENT(handle(), 2, info);
         }
         return;
     }
@@ -78,15 +81,18 @@ void Database::Process() {
 }
 
 void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) {
+    Nan::HandleScope scope;
+
     if (!open && locked) {
-        EXCEPTION(String::New("Database is closed"), SQLITE_MISUSE, exception);
-        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
+        EXCEPTION(Nan::New("Database is closed").ToLocalChecked(), SQLITE_MISUSE, exception);
+        Local<Function> cb = Nan::New(baton->callback);
+        if (!cb.IsEmpty() && cb->IsFunction()) {
             Local<Value> argv[] = { exception };
-            TRY_CATCH_CALL(handle_, baton->callback, 1, argv);
+            TRY_CATCH_CALL(handle(), cb, 1, argv);
         }
         else {
-            Local<Value> argv[] = { String::NewSymbol("error"), exception };
-            EMIT_EVENT(handle_, 2, argv);
+            Local<Value> argv[] = { Nan::New("error").ToLocalChecked(), exception };
+            EMIT_EVENT(handle(), 2, argv);
         }
         return;
     }
@@ -100,41 +106,37 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) {
     }
 }
 
-Handle<Value> Database::New(const Arguments& args) {
-    HandleScope scope;
-
-    if (!args.IsConstructCall()) {
-        return ThrowException(Exception::TypeError(
-            String::New("Use the new operator to create new Database objects"))
-        );
+NAN_METHOD(Database::New) {
+    if (!info.IsConstructCall()) {
+        return Nan::ThrowTypeError("Use the new operator to create new Database objects");
     }
 
     REQUIRE_ARGUMENT_STRING(0, filename);
     int pos = 1;
 
     int mode;
-    if (args.Length() >= pos && args[pos]->IsInt32()) {
-        mode = args[pos++]->Int32Value();
+    if (info.Length() >= pos && info[pos]->IsInt32()) {
+        mode = Nan::To<int>(info[pos++]).FromJust();
     } else {
         mode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX;
     }
 
     Local<Function> callback;
-    if (args.Length() >= pos && args[pos]->IsFunction()) {
-        callback = Local<Function>::Cast(args[pos++]);
+    if (info.Length() >= pos && info[pos]->IsFunction()) {
+        callback = Local<Function>::Cast(info[pos++]);
     }
 
     Database* db = new Database();
-    db->Wrap(args.This());
+    db->Wrap(info.This());
 
-    args.This()->Set(String::NewSymbol("filename"), args[0]->ToString(), ReadOnly);
-    args.This()->Set(String::NewSymbol("mode"), Integer::New(mode), ReadOnly);
+    info.This()->ForceSet(Nan::New("filename").ToLocalChecked(), info[0].As<String>(), ReadOnly);
+    info.This()->ForceSet(Nan::New("mode").ToLocalChecked(), Nan::New(mode), ReadOnly);
 
     // Start opening the database.
     OpenBaton* baton = new OpenBaton(db, callback, *filename, mode);
     Work_BeginOpen(baton);
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
 void Database::Work_BeginOpen(Baton* baton) {
@@ -149,75 +151,76 @@ void Database::Work_Open(uv_work_t* req) {
 
     baton->status = sqlite3_open_v2(
         baton->filename.c_str(),
-        &db->handle,
+        &db->_handle,
         baton->mode,
         NULL
     );
 
     if (baton->status != SQLITE_OK) {
-        baton->message = std::string(sqlite3_errmsg(db->handle));
-        sqlite3_close(db->handle);
-        db->handle = NULL;
+        baton->message = std::string(sqlite3_errmsg(db->_handle));
+        sqlite3_close(db->_handle);
+        db->_handle = NULL;
     }
     else {
         // Set default database handle values.
-        sqlite3_busy_timeout(db->handle, 1000);
+        sqlite3_busy_timeout(db->_handle, 1000);
     }
 }
 
 void Database::Work_AfterOpen(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     OpenBaton* baton = static_cast<OpenBaton*>(req->data);
     Database* db = baton->db;
 
     Local<Value> argv[1];
     if (baton->status != SQLITE_OK) {
-        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
+        EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception);
         argv[0] = exception;
     }
     else {
         db->open = true;
-        argv[0] = Local<Value>::New(Null());
+        argv[0] = Nan::Null();
     }
 
-    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
+    Local<Function> cb = Nan::New(baton->callback);
+
+    if (!cb.IsEmpty() && cb->IsFunction()) {
+        TRY_CATCH_CALL(db->handle(), cb, 1, argv);
     }
     else if (!db->open) {
-        Local<Value> args[] = { String::NewSymbol("error"), argv[0] };
-        EMIT_EVENT(db->handle_, 2, args);
+        Local<Value> info[] = { Nan::New("error").ToLocalChecked(), argv[0] };
+        EMIT_EVENT(db->handle(), 2, info);
     }
 
     if (db->open) {
-        Local<Value> args[] = { String::NewSymbol("open") };
-        EMIT_EVENT(db->handle_, 1, args);
+        Local<Value> info[] = { Nan::New("open").ToLocalChecked() };
+        EMIT_EVENT(db->handle(), 1, info);
         db->Process();
     }
 
     delete baton;
 }
 
-Handle<Value> Database::OpenGetter(Local<String> str, const AccessorInfo& accessor) {
-    HandleScope scope;
-    Database* db = ObjectWrap::Unwrap<Database>(accessor.This());
-    return Boolean::New(db->open);
+NAN_GETTER(Database::OpenGetter) {
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
+    info.GetReturnValue().Set(db->open);
 }
 
-Handle<Value> Database::Close(const Arguments& args) {
-    HandleScope scope;
-    Database* db = ObjectWrap::Unwrap<Database>(args.This());
+NAN_METHOD(Database::Close) {
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
     OPTIONAL_ARGUMENT_FUNCTION(0, callback);
 
     Baton* baton = new Baton(db, callback);
     db->Schedule(Work_BeginClose, baton, true);
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
 void Database::Work_BeginClose(Baton* baton) {
     assert(baton->db->locked);
     assert(baton->db->open);
-    assert(baton->db->handle);
+    assert(baton->db->_handle);
     assert(baton->db->pending == 0);
 
     baton->db->RemoveCallbacks();
@@ -230,149 +233,147 @@ void Database::Work_Close(uv_work_t* req) {
     Baton* baton = static_cast<Baton*>(req->data);
     Database* db = baton->db;
 
-    baton->status = sqlite3_close(db->handle);
+    baton->status = sqlite3_close(db->_handle);
 
     if (baton->status != SQLITE_OK) {
-        baton->message = std::string(sqlite3_errmsg(db->handle));
+        baton->message = std::string(sqlite3_errmsg(db->_handle));
     }
     else {
-        db->handle = NULL;
+        db->_handle = NULL;
     }
 }
 
 void Database::Work_AfterClose(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     Baton* baton = static_cast<Baton*>(req->data);
     Database* db = baton->db;
 
     Local<Value> argv[1];
     if (baton->status != SQLITE_OK) {
-        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
+        EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception);
         argv[0] = exception;
     }
     else {
         db->open = false;
         // Leave db->locked to indicate that this db object has reached
         // the end of its life.
-        argv[0] = Local<Value>::New(Null());
+        argv[0] = Nan::Null();
     }
 
+    Local<Function> cb = Nan::New(baton->callback);
+
     // Fire callbacks.
-    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
+    if (!cb.IsEmpty() && cb->IsFunction()) {
+        TRY_CATCH_CALL(db->handle(), cb, 1, argv);
     }
     else if (db->open) {
-        Local<Value> args[] = { String::NewSymbol("error"), argv[0] };
-        EMIT_EVENT(db->handle_, 2, args);
+        Local<Value> info[] = { Nan::New("error").ToLocalChecked(), argv[0] };
+        EMIT_EVENT(db->handle(), 2, info);
     }
 
     if (!db->open) {
-        Local<Value> args[] = { String::NewSymbol("close"), argv[0] };
-        EMIT_EVENT(db->handle_, 1, args);
+        Local<Value> info[] = { Nan::New("close").ToLocalChecked(), argv[0] };
+        EMIT_EVENT(db->handle(), 1, info);
         db->Process();
     }
 
     delete baton;
 }
 
-Handle<Value> Database::Serialize(const Arguments& args) {
-    HandleScope scope;
-    Database* db = ObjectWrap::Unwrap<Database>(args.This());
+NAN_METHOD(Database::Serialize) {
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
     OPTIONAL_ARGUMENT_FUNCTION(0, callback);
 
     bool before = db->serialize;
     db->serialize = true;
 
     if (!callback.IsEmpty() && callback->IsFunction()) {
-        TRY_CATCH_CALL(args.This(), callback, 0, NULL);
+        TRY_CATCH_CALL(info.This(), callback, 0, NULL);
         db->serialize = before;
     }
 
     db->Process();
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
-Handle<Value> Database::Parallelize(const Arguments& args) {
-    HandleScope scope;
-    Database* db = ObjectWrap::Unwrap<Database>(args.This());
+NAN_METHOD(Database::Parallelize) {
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
     OPTIONAL_ARGUMENT_FUNCTION(0, callback);
 
     bool before = db->serialize;
     db->serialize = false;
 
     if (!callback.IsEmpty() && callback->IsFunction()) {
-        TRY_CATCH_CALL(args.This(), callback, 0, NULL);
+        TRY_CATCH_CALL(info.This(), callback, 0, NULL);
         db->serialize = before;
     }
 
     db->Process();
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
-Handle<Value> Database::Configure(const Arguments& args) {
-    HandleScope scope;
-    Database* db = ObjectWrap::Unwrap<Database>(args.This());
+NAN_METHOD(Database::Configure) {
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
 
     REQUIRE_ARGUMENTS(2);
 
-    if (args[0]->Equals(String::NewSymbol("trace"))) {
+    if (Nan::Equals(info[0], Nan::New("trace").ToLocalChecked()).FromJust()) {
         Local<Function> handle;
         Baton* baton = new Baton(db, handle);
         db->Schedule(RegisterTraceCallback, baton);
     }
-    else if (args[0]->Equals(String::NewSymbol("profile"))) {
+    else if (Nan::Equals(info[0], Nan::New("profile").ToLocalChecked()).FromJust()) {
         Local<Function> handle;
         Baton* baton = new Baton(db, handle);
         db->Schedule(RegisterProfileCallback, baton);
     }
-    else if (args[0]->Equals(String::NewSymbol("busyTimeout"))) {
-        if (!args[1]->IsInt32()) {
-            return ThrowException(Exception::TypeError(
-                String::New("Value must be an integer"))
-            );
+    else if (Nan::Equals(info[0], Nan::New("busyTimeout").ToLocalChecked()).FromJust()) {
+        if (!info[1]->IsInt32()) {
+            return Nan::ThrowTypeError("Value must be an integer");
         }
         Local<Function> handle;
         Baton* baton = new Baton(db, handle);
-        baton->status = args[1]->Int32Value();
+        baton->status = Nan::To<int>(info[1]).FromJust();
         db->Schedule(SetBusyTimeout, baton);
     }
     else {
-        return ThrowException(Exception::Error(String::Concat(
-            args[0]->ToString(),
-            String::NewSymbol(" is not a valid configuration option")
+        return Nan::ThrowError(Exception::Error(String::Concat(
+            Nan::To<String>(info[0]).ToLocalChecked(),
+            Nan::New(" is not a valid configuration option").ToLocalChecked()
         )));
     }
 
     db->Process();
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
 void Database::SetBusyTimeout(Baton* baton) {
     assert(baton->db->open);
-    assert(baton->db->handle);
+    assert(baton->db->_handle);
 
     // Abuse the status field for passing the timeout.
-    sqlite3_busy_timeout(baton->db->handle, baton->status);
+    sqlite3_busy_timeout(baton->db->_handle, baton->status);
 
     delete baton;
 }
 
 void Database::RegisterTraceCallback(Baton* baton) {
     assert(baton->db->open);
-    assert(baton->db->handle);
+    assert(baton->db->_handle);
     Database* db = baton->db;
 
     if (db->debug_trace == NULL) {
         // Add it.
         db->debug_trace = new AsyncTrace(db, TraceCallback);
-        sqlite3_trace(db->handle, TraceCallback, db);
+        sqlite3_trace(db->_handle, TraceCallback, db);
     }
     else {
         // Remove it.
-        sqlite3_trace(db->handle, NULL, NULL);
+        sqlite3_trace(db->_handle, NULL, NULL);
         db->debug_trace->finish();
         db->debug_trace = NULL;
     }
@@ -388,28 +389,29 @@ void Database::TraceCallback(void* db, const char* sql) {
 
 void Database::TraceCallback(Database* db, std::string* sql) {
     // Note: This function is called in the main V8 thread.
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     Local<Value> argv[] = {
-        String::NewSymbol("trace"),
-        String::New(sql->c_str())
+        Nan::New("trace").ToLocalChecked(),
+        Nan::New(sql->c_str()).ToLocalChecked()
     };
-    EMIT_EVENT(db->handle_, 2, argv);
+    EMIT_EVENT(db->handle(), 2, argv);
     delete sql;
 }
 
 void Database::RegisterProfileCallback(Baton* baton) {
     assert(baton->db->open);
-    assert(baton->db->handle);
+    assert(baton->db->_handle);
     Database* db = baton->db;
 
     if (db->debug_profile == NULL) {
         // Add it.
         db->debug_profile = new AsyncProfile(db, ProfileCallback);
-        sqlite3_profile(db->handle, ProfileCallback, db);
+        sqlite3_profile(db->_handle, ProfileCallback, db);
     }
     else {
         // Remove it.
-        sqlite3_profile(db->handle, NULL, NULL);
+        sqlite3_profile(db->_handle, NULL, NULL);
         db->debug_profile->finish();
         db->debug_profile = NULL;
     }
@@ -427,29 +429,30 @@ void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs)
 }
 
 void Database::ProfileCallback(Database *db, ProfileInfo* info) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     Local<Value> argv[] = {
-        String::NewSymbol("profile"),
-        String::New(info->sql.c_str()),
-        Integer::New((double)info->nsecs / 1000000.0)
+        Nan::New("profile").ToLocalChecked(),
+        Nan::New(info->sql.c_str()).ToLocalChecked(),
+        Nan::New<Number>((double)info->nsecs / 1000000.0)
     };
-    EMIT_EVENT(db->handle_, 3, argv);
+    EMIT_EVENT(db->handle(), 3, argv);
     delete info;
 }
 
 void Database::RegisterUpdateCallback(Baton* baton) {
     assert(baton->db->open);
-    assert(baton->db->handle);
+    assert(baton->db->_handle);
     Database* db = baton->db;
 
     if (db->update_event == NULL) {
         // Add it.
         db->update_event = new AsyncUpdate(db, UpdateCallback);
-        sqlite3_update_hook(db->handle, UpdateCallback, db);
+        sqlite3_update_hook(db->_handle, UpdateCallback, db);
     }
     else {
         // Remove it.
-        sqlite3_update_hook(db->handle, NULL, NULL);
+        sqlite3_update_hook(db->_handle, NULL, NULL);
         db->update_event->finish();
         db->update_event = NULL;
     }
@@ -470,21 +473,20 @@ void Database::UpdateCallback(void* db, int type, const char* database,
 }
 
 void Database::UpdateCallback(Database *db, UpdateInfo* info) {
-    HandleScope scope;
+    Nan::HandleScope scope;
 
     Local<Value> argv[] = {
-        String::NewSymbol(sqlite_authorizer_string(info->type)),
-        String::New(info->database.c_str()),
-        String::New(info->table.c_str()),
-        Integer::New(info->rowid),
+        Nan::New(sqlite_authorizer_string(info->type)).ToLocalChecked(),
+        Nan::New(info->database.c_str()).ToLocalChecked(),
+        Nan::New(info->table.c_str()).ToLocalChecked(),
+        Nan::New<Number>(info->rowid),
     };
-    EMIT_EVENT(db->handle_, 4, argv);
+    EMIT_EVENT(db->handle(), 4, argv);
     delete info;
 }
 
-Handle<Value> Database::Exec(const Arguments& args) {
-    HandleScope scope;
-    Database* db = ObjectWrap::Unwrap<Database>(args.This());
+NAN_METHOD(Database::Exec) {
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
 
     REQUIRE_ARGUMENT_STRING(0, sql);
     OPTIONAL_ARGUMENT_FUNCTION(1, callback);
@@ -492,13 +494,13 @@ Handle<Value> Database::Exec(const Arguments& args) {
     Baton* baton = new ExecBaton(db, callback, *sql);
     db->Schedule(Work_BeginExec, baton, true);
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
 void Database::Work_BeginExec(Baton* baton) {
     assert(baton->db->locked);
     assert(baton->db->open);
-    assert(baton->db->handle);
+    assert(baton->db->_handle);
     assert(baton->db->pending == 0);
     int status = uv_queue_work(uv_default_loop(),
         &baton->request, Work_Exec, (uv_after_work_cb)Work_AfterExec);
@@ -510,7 +512,7 @@ void Database::Work_Exec(uv_work_t* req) {
 
     char* message = NULL;
     baton->status = sqlite3_exec(
-        baton->db->handle,
+        baton->db->_handle,
         baton->sql.c_str(),
         NULL,
         NULL,
@@ -524,26 +526,28 @@ void Database::Work_Exec(uv_work_t* req) {
 }
 
 void Database::Work_AfterExec(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     ExecBaton* baton = static_cast<ExecBaton*>(req->data);
     Database* db = baton->db;
 
+    Local<Function> cb = Nan::New(baton->callback);
 
     if (baton->status != SQLITE_OK) {
-        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
+        EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception);
 
-        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
+        if (!cb.IsEmpty() && cb->IsFunction()) {
             Local<Value> argv[] = { exception };
-            TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
+            TRY_CATCH_CALL(db->handle(), cb, 1, argv);
         }
         else {
-            Local<Value> args[] = { String::NewSymbol("error"), exception };
-            EMIT_EVENT(db->handle_, 2, args);
+            Local<Value> info[] = { Nan::New("error").ToLocalChecked(), exception };
+            EMIT_EVENT(db->handle(), 2, info);
         }
     }
-    else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-        Local<Value> argv[] = { Local<Value>::New(Null()) };
-        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
+    else if (!cb.IsEmpty() && cb->IsFunction()) {
+        Local<Value> argv[] = { Nan::Null() };
+        TRY_CATCH_CALL(db->handle(), cb, 1, argv);
     }
 
     db->Process();
@@ -551,29 +555,29 @@ void Database::Work_AfterExec(uv_work_t* req) {
     delete baton;
 }
 
-Handle<Value> Database::Wait(const Arguments& args) {
-    HandleScope scope;
-    Database* db = ObjectWrap::Unwrap<Database>(args.This());
+NAN_METHOD(Database::Wait) {
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
 
     OPTIONAL_ARGUMENT_FUNCTION(0, callback);
 
     Baton* baton = new Baton(db, callback);
     db->Schedule(Work_Wait, baton, true);
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
 void Database::Work_Wait(Baton* baton) {
-    HandleScope scope;
+    Nan::HandleScope scope;
 
     assert(baton->db->locked);
     assert(baton->db->open);
-    assert(baton->db->handle);
+    assert(baton->db->_handle);
     assert(baton->db->pending == 0);
 
-    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-        Local<Value> argv[] = { Local<Value>::New(Null()) };
-        TRY_CATCH_CALL(baton->db->handle_, baton->callback, 1, argv);
+    Local<Function> cb = Nan::New(baton->callback);
+    if (!cb.IsEmpty() && cb->IsFunction()) {
+        Local<Value> argv[] = { Nan::Null() };
+        TRY_CATCH_CALL(baton->db->handle(), cb, 1, argv);
     }
 
     baton->db->Process();
@@ -581,9 +585,8 @@ void Database::Work_Wait(Baton* baton) {
     delete baton;
 }
 
-Handle<Value> Database::LoadExtension(const Arguments& args) {
-    HandleScope scope;
-    Database* db = ObjectWrap::Unwrap<Database>(args.This());
+NAN_METHOD(Database::LoadExtension) {
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
 
     REQUIRE_ARGUMENT_STRING(0, filename);
     OPTIONAL_ARGUMENT_FUNCTION(1, callback);
@@ -591,33 +594,33 @@ Handle<Value> Database::LoadExtension(const Arguments& args) {
     Baton* baton = new LoadExtensionBaton(db, callback, *filename);
     db->Schedule(Work_BeginLoadExtension, baton, true);
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
 void Database::Work_BeginLoadExtension(Baton* baton) {
     assert(baton->db->locked);
     assert(baton->db->open);
-    assert(baton->db->handle);
+    assert(baton->db->_handle);
     assert(baton->db->pending == 0);
     int status = uv_queue_work(uv_default_loop(),
-        &baton->request, Work_LoadExtension, (uv_after_work_cb)Work_AfterLoadExtension);
+        &baton->request, Work_LoadExtension, reinterpret_cast<uv_after_work_cb>(Work_AfterLoadExtension));
     assert(status == 0);
 }
 
 void Database::Work_LoadExtension(uv_work_t* req) {
     LoadExtensionBaton* baton = static_cast<LoadExtensionBaton*>(req->data);
 
-    sqlite3_enable_load_extension(baton->db->handle, 1);
+    sqlite3_enable_load_extension(baton->db->_handle, 1);
 
     char* message = NULL;
     baton->status = sqlite3_load_extension(
-        baton->db->handle,
+        baton->db->_handle,
         baton->filename.c_str(),
         0,
         &message
     );
 
-    sqlite3_enable_load_extension(baton->db->handle, 0);
+    sqlite3_enable_load_extension(baton->db->_handle, 0);
 
     if (baton->status != SQLITE_OK && message != NULL) {
         baton->message = std::string(message);
@@ -626,25 +629,27 @@ void Database::Work_LoadExtension(uv_work_t* req) {
 }
 
 void Database::Work_AfterLoadExtension(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     LoadExtensionBaton* baton = static_cast<LoadExtensionBaton*>(req->data);
     Database* db = baton->db;
+    Local<Function> cb = Nan::New(baton->callback);
 
     if (baton->status != SQLITE_OK) {
-        EXCEPTION(String::New(baton->message.c_str()), baton->status, exception);
+        EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception);
 
-        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
+        if (!cb.IsEmpty() && cb->IsFunction()) {
             Local<Value> argv[] = { exception };
-            TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
+            TRY_CATCH_CALL(db->handle(), cb, 1, argv);
         }
         else {
-            Local<Value> args[] = { String::NewSymbol("error"), exception };
-            EMIT_EVENT(db->handle_, 2, args);
+            Local<Value> info[] = { Nan::New("error").ToLocalChecked(), exception };
+            EMIT_EVENT(db->handle(), 2, info);
         }
     }
-    else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-        Local<Value> argv[] = { Local<Value>::New(Null()) };
-        TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv);
+    else if (!cb.IsEmpty() && cb->IsFunction()) {
+        Local<Value> argv[] = { Nan::Null() };
+        TRY_CATCH_CALL(db->handle(), cb, 1, argv);
     }
 
     db->Process();
diff --git a/src/database.h b/src/database.h
index a051dae..8aeabfd 100644
--- a/src/database.h
+++ b/src/database.h
@@ -1,68 +1,70 @@
+
 #ifndef NODE_SQLITE3_SRC_DATABASE_H
 #define NODE_SQLITE3_SRC_DATABASE_H
 
-#include <node.h>
 
 #include <string>
 #include <queue>
 
 #include <sqlite3.h>
+#include <nan.h>
+
 #include "async.h"
 
 using namespace v8;
-using namespace node;
 
 namespace node_sqlite3 {
 
 class Database;
 
 
-class Database : public ObjectWrap {
+class Database : public Nan::ObjectWrap {
 public:
-    static Persistent<FunctionTemplate> constructor_template;
-    static void Init(Handle<Object> target);
+    static Nan::Persistent<FunctionTemplate> constructor_template;
+    static NAN_MODULE_INIT(Init);
 
-    static inline bool HasInstance(Handle<Value> val) {
+    static inline bool HasInstance(Local<Value> val) {
+        Nan::HandleScope scope;
         if (!val->IsObject()) return false;
-        Local<Object> obj = val->ToObject();
-        return constructor_template->HasInstance(obj);
+        Local<Object> obj = val.As<Object>();
+        return Nan::New(constructor_template)->HasInstance(obj);
     }
 
     struct Baton {
         uv_work_t request;
         Database* db;
-        Persistent<Function> callback;
+        Nan::Persistent<Function> callback;
         int status;
         std::string message;
 
-        Baton(Database* db_, Handle<Function> cb_) :
+        Baton(Database* db_, Local<Function> cb_) :
                 db(db_), status(SQLITE_OK) {
             db->Ref();
             request.data = this;
-            callback = Persistent<Function>::New(cb_);
+            callback.Reset(cb_);
         }
         virtual ~Baton() {
             db->Unref();
-            callback.Dispose();
+            callback.Reset();
         }
     };
 
     struct OpenBaton : Baton {
         std::string filename;
         int mode;
-        OpenBaton(Database* db_, Handle<Function> cb_, const char* filename_, int mode_) :
+        OpenBaton(Database* db_, Local<Function> cb_, const char* filename_, int mode_) :
             Baton(db_, cb_), filename(filename_), mode(mode_) {}
     };
 
     struct ExecBaton : Baton {
         std::string sql;
-        ExecBaton(Database* db_, Handle<Function> cb_, const char* sql_) :
+        ExecBaton(Database* db_, Local<Function> cb_, const char* sql_) :
             Baton(db_, cb_), sql(sql_) {}
     };
 
     struct LoadExtensionBaton : Baton {
         std::string filename;
-        LoadExtensionBaton(Database* db_, Handle<Function> cb_, const char* filename_) :
+        LoadExtensionBaton(Database* db_, Local<Function> cb_, const char* filename_) :
             Baton(db_, cb_), filename(filename_) {}
     };
 
@@ -98,8 +100,8 @@ public:
     friend class Statement;
 
 protected:
-    Database() : ObjectWrap(),
-        handle(NULL),
+    Database() : Nan::ObjectWrap(),
+        _handle(NULL),
         open(false),
         locked(false),
         pending(0),
@@ -107,48 +109,47 @@ protected:
         debug_trace(NULL),
         debug_profile(NULL),
         update_event(NULL) {
-
     }
 
     ~Database() {
         RemoveCallbacks();
-        sqlite3_close(handle);
-        handle = NULL;
+        sqlite3_close(_handle);
+        _handle = NULL;
         open = false;
     }
 
-    static Handle<Value> New(const Arguments& args);
+    static NAN_METHOD(New);
     static void Work_BeginOpen(Baton* baton);
     static void Work_Open(uv_work_t* req);
     static void Work_AfterOpen(uv_work_t* req);
 
-    static Handle<Value> OpenGetter(Local<String> str, const AccessorInfo& accessor);
+    static NAN_GETTER(OpenGetter);
 
     void Schedule(Work_Callback callback, Baton* baton, bool exclusive = false);
     void Process();
 
-    static Handle<Value> Exec(const Arguments& args);
+    static NAN_METHOD(Exec);
     static void Work_BeginExec(Baton* baton);
     static void Work_Exec(uv_work_t* req);
     static void Work_AfterExec(uv_work_t* req);
 
-    static Handle<Value> Wait(const Arguments& args);
+    static NAN_METHOD(Wait);
     static void Work_Wait(Baton* baton);
 
-    static Handle<Value> Close(const Arguments& args);
+    static NAN_METHOD(Close);
     static void Work_BeginClose(Baton* baton);
     static void Work_Close(uv_work_t* req);
     static void Work_AfterClose(uv_work_t* req);
 
-    static Handle<Value> LoadExtension(const Arguments& args);
+    static NAN_METHOD(LoadExtension);
     static void Work_BeginLoadExtension(Baton* baton);
     static void Work_LoadExtension(uv_work_t* req);
     static void Work_AfterLoadExtension(uv_work_t* req);
 
-    static Handle<Value> Serialize(const Arguments& args);
-    static Handle<Value> Parallelize(const Arguments& args);
+    static NAN_METHOD(Serialize);
+    static NAN_METHOD(Parallelize);
 
-    static Handle<Value> Configure(const Arguments& args);
+    static NAN_METHOD(Configure);
 
     static void SetBusyTimeout(Baton* baton);
 
@@ -167,7 +168,7 @@ protected:
     void RemoveCallbacks();
 
 protected:
-    sqlite3* handle;
+    sqlite3* _handle;
 
     bool open;
     bool locked;
diff --git a/src/gcc-preinclude.h b/src/gcc-preinclude.h
index c515fa6..38c9138 100644
--- a/src/gcc-preinclude.h
+++ b/src/gcc-preinclude.h
@@ -1,4 +1,6 @@
 
 // https://rjpower9000.wordpress.com/2012/04/09/fun-with-shared-libraries-version-glibc_2-14-not-found/
 
+#if defined(__linux__) && defined(__x86_64__)
 __asm__(".symver memcpy,memcpy at GLIBC_2.2.5");
+#endif
diff --git a/src/macros.h b/src/macros.h
index dbd14d0..38399ee 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -6,123 +6,110 @@ const char* sqlite_authorizer_string(int type);
 
 
 #define REQUIRE_ARGUMENTS(n)                                                   \
-    if (args.Length() < (n)) {                                                 \
-        return ThrowException(                                                 \
-            Exception::TypeError(String::New("Expected " #n "arguments"))      \
-        );                                                                     \
+    if (info.Length() < (n)) {                                                 \
+        return Nan::ThrowTypeError("Expected " #n "arguments");                \
     }
 
 
 #define REQUIRE_ARGUMENT_EXTERNAL(i, var)                                      \
-    if (args.Length() <= (i) || !args[i]->IsExternal()) {                      \
-        return ThrowException(                                                 \
-            Exception::TypeError(String::New("Argument " #i " invalid"))       \
-        );                                                                     \
+    if (info.Length() <= (i) || !info[i]->IsExternal()) {                      \
+        return Nan::ThrowTypeError("Argument " #i " invalid");                 \
     }                                                                          \
-    Local<External> var = Local<External>::Cast(args[i]);
+    Local<External> var = Local<External>::Cast(info[i]);
 
 
 #define REQUIRE_ARGUMENT_FUNCTION(i, var)                                      \
-    if (args.Length() <= (i) || !args[i]->IsFunction()) {                      \
-        return ThrowException(Exception::TypeError(                            \
-            String::New("Argument " #i " must be a function"))                 \
-        );                                                                     \
+    if (info.Length() <= (i) || !info[i]->IsFunction()) {                      \
+        return Nan::ThrowTypeError("Argument " #i " must be a function");      \
     }                                                                          \
-    Local<Function> var = Local<Function>::Cast(args[i]);
+    Local<Function> var = Local<Function>::Cast(info[i]);
 
 
 #define REQUIRE_ARGUMENT_STRING(i, var)                                        \
-    if (args.Length() <= (i) || !args[i]->IsString()) {                        \
-        return ThrowException(Exception::TypeError(                            \
-            String::New("Argument " #i " must be a string"))                   \
-        );                                                                     \
+    if (info.Length() <= (i) || !info[i]->IsString()) {                        \
+        return Nan::ThrowTypeError("Argument " #i " must be a string");        \
     }                                                                          \
-    String::Utf8Value var(args[i]->ToString());
+    Nan::Utf8String var(info[i]);
 
 
 #define OPTIONAL_ARGUMENT_FUNCTION(i, var)                                     \
     Local<Function> var;                                                       \
-    if (args.Length() > i && !args[i]->IsUndefined()) {                        \
-        if (!args[i]->IsFunction()) {                                          \
-            return ThrowException(Exception::TypeError(                        \
-                String::New("Argument " #i " must be a function"))             \
-            );                                                                 \
+    if (info.Length() > i && !info[i]->IsUndefined()) {                        \
+        if (!info[i]->IsFunction()) {                                          \
+            return Nan::ThrowTypeError("Argument " #i " must be a function");  \
         }                                                                      \
-        var = Local<Function>::Cast(args[i]);                                  \
+        var = Local<Function>::Cast(info[i]);                                  \
     }
 
 
 #define OPTIONAL_ARGUMENT_INTEGER(i, var, default)                             \
     int var;                                                                   \
-    if (args.Length() <= (i)) {                                                \
+    if (info.Length() <= (i)) {                                                \
         var = (default);                                                       \
     }                                                                          \
-    else if (args[i]->IsInt32()) {                                             \
-        var = args[i]->Int32Value();                                           \
+    else if (info[i]->IsInt32()) {                                             \
+        var = Nan::To<int32_t>(info[i]).FromJust();                            \
     }                                                                          \
     else {                                                                     \
-        return ThrowException(Exception::TypeError(                            \
-            String::New("Argument " #i " must be an integer"))                 \
-        );                                                                     \
+        return Nan::ThrowTypeError("Argument " #i " must be an integer");      \
     }
 
 
 #define DEFINE_CONSTANT_INTEGER(target, constant, name)                        \
-    (target)->Set(                                                             \
-        String::NewSymbol(#name),                                              \
-        Integer::New(constant),                                                \
+    Nan::ForceSet(target,                                                      \
+        Nan::New(#name).ToLocalChecked(),                                      \
+        Nan::New<Integer>(constant),                                           \
         static_cast<PropertyAttribute>(ReadOnly | DontDelete)                  \
     );
 
 #define DEFINE_CONSTANT_STRING(target, constant, name)                         \
-    (target)->Set(                                                             \
-        String::NewSymbol(#name),                                              \
-        String::NewSymbol(constant),                                           \
+    Nan::ForceSet(target,                                                      \
+        Nan::New(#name).ToLocalChecked(),                                      \
+        Nan::New(constant).ToLocalChecked(),                                   \
         static_cast<PropertyAttribute>(ReadOnly | DontDelete)                  \
     );
 
 
 #define NODE_SET_GETTER(target, name, function)                                \
-    (target)->InstanceTemplate()                                               \
-        ->SetAccessor(String::NewSymbol(name), (function));
+    Nan::SetAccessor((target)->InstanceTemplate(),                             \
+        Nan::New(name).ToLocalChecked(), (function));
 
 #define GET_STRING(source, name, property)                                     \
-    String::Utf8Value name((source)->Get(String::NewSymbol(property)));
+    Nan::Utf8String name(Nan::Get(source,                                      \
+        Nan::New(prop).ToLocalChecked()).ToLocalChecked());
 
-#define GET_INTEGER(source, name, property)                                    \
-    int name = (source)->Get(String::NewSymbol(property))->Int32Value();
+#define GET_INTEGER(source, name, prop)                                        \
+    int name = Nan::To<int>(Nan::Get(source,                                   \
+        Nan::New(property).ToLocalChecked()).ToLocalChecked()).FromJust();
 
 #define EXCEPTION(msg, errno, name)                                            \
     Local<Value> name = Exception::Error(                                      \
         String::Concat(                                                        \
             String::Concat(                                                    \
-                String::NewSymbol(sqlite_code_string(errno)),                  \
-                String::NewSymbol(": ")                                        \
+                Nan::New(sqlite_code_string(errno)).ToLocalChecked(),          \
+                Nan::New(": ").ToLocalChecked()                                \
             ),                                                                 \
             (msg)                                                              \
         )                                                                      \
     );                                                                         \
-    Local<Object> name ##_obj = name->ToObject();                              \
-    name ##_obj->Set(NODE_PSYMBOL("errno"), Integer::New(errno));              \
-    name ##_obj->Set(NODE_PSYMBOL("code"),                                     \
-        String::NewSymbol(sqlite_code_string(errno)));
+    Local<Object> name ##_obj = name.As<Object>();                             \
+    Nan::Set(name ##_obj, Nan::New("errno").ToLocalChecked(), Nan::New(errno));\
+    Nan::Set(name ##_obj, Nan::New("code").ToLocalChecked(),                   \
+        Nan::New(sqlite_code_string(errno)).ToLocalChecked());
 
 
 #define EMIT_EVENT(obj, argc, argv)                                            \
     TRY_CATCH_CALL((obj),                                                      \
-        Local<Function>::Cast((obj)->Get(String::NewSymbol("emit"))),          \
+        Nan::Get(obj,                                                          \
+            Nan::New("emit").ToLocalChecked()).ToLocalChecked().As<Function>(),\
         argc, argv                                                             \
     );
 
 #define TRY_CATCH_CALL(context, callback, argc, argv)                          \
-{   TryCatch try_catch;                                                        \
-    (callback)->Call((context), (argc), (argv));                               \
-    if (try_catch.HasCaught()) {                                               \
-        FatalException(try_catch);                                             \
-    }                                                                          }
-
-#define WORK_DEFINITION(name)                                                 \
-    static Handle<Value> name(const Arguments& args);                          \
+    Nan::MakeCallback((context), (callback), (argc), (argv))
+
+#define WORK_DEFINITION(name)                                                  \
+    static NAN_METHOD(name);                                                   \
     static void Work_Begin##name(Baton* baton);                                \
     static void Work_##name(uv_work_t* req);                                   \
     static void Work_After##name(uv_work_t* req);
@@ -136,7 +123,8 @@ const char* sqlite_authorizer_string(int type);
     baton->stmt->locked = true;                                                \
     baton->stmt->db->pending++;                                                \
     int status = uv_queue_work(uv_default_loop(),                              \
-        &baton->request, Work_##type, (uv_after_work_cb)Work_After##type);                       \
+        &baton->request,                                                       \
+        Work_##type, reinterpret_cast<uv_after_work_cb>(Work_After##type));    \
     assert(status == 0);
 
 #define STATEMENT_INIT(type)                                                   \
@@ -164,4 +152,3 @@ const char* sqlite_authorizer_string(int type);
     }
 
 #endif
-
diff --git a/src/node_sqlite3.cc b/src/node_sqlite3.cc
index b588bbd..d8b459a 100644
--- a/src/node_sqlite3.cc
+++ b/src/node_sqlite3.cc
@@ -1,6 +1,3 @@
-#include <node.h>
-#include <node_buffer.h>
-
 #include <stdint.h>
 #include <sstream>
 #include <cstring>
@@ -15,7 +12,9 @@ using namespace node_sqlite3;
 
 namespace {
 
-void RegisterModule(v8::Handle<Object> target) {
+NAN_MODULE_INIT(RegisterModule) {
+    Nan::HandleScope scope;
+
     Database::Init(target);
     Statement::Init(target);
 
@@ -103,4 +102,4 @@ const char* sqlite_authorizer_string(int type) {
     }
 }
 
-NODE_MODULE(node_sqlite3, RegisterModule);
+NODE_MODULE(node_sqlite3, RegisterModule)
diff --git a/src/statement.cc b/src/statement.cc
index 86df315..0166b72 100644
--- a/src/statement.cc
+++ b/src/statement.cc
@@ -9,27 +9,27 @@
 
 using namespace node_sqlite3;
 
-Persistent<FunctionTemplate> Statement::constructor_template;
+Nan::Persistent<FunctionTemplate> Statement::constructor_template;
 
-void Statement::Init(Handle<Object> target) {
-    HandleScope scope;
+NAN_MODULE_INIT(Statement::Init) {
+    Nan::HandleScope scope;
 
-    Local<FunctionTemplate> t = FunctionTemplate::New(New);
+    Local<FunctionTemplate> t = Nan::New<FunctionTemplate>(New);
 
-    constructor_template = Persistent<FunctionTemplate>::New(t);
-    constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
-    constructor_template->SetClassName(String::NewSymbol("Statement"));
+    t->InstanceTemplate()->SetInternalFieldCount(1);
+    t->SetClassName(Nan::New("Statement").ToLocalChecked());
 
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "bind", Bind);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "get", Get);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "run", Run);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "all", All);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "each", Each);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "reset", Reset);
-    NODE_SET_PROTOTYPE_METHOD(constructor_template, "finalize", Finalize);
+    Nan::SetPrototypeMethod(t, "bind", Bind);
+    Nan::SetPrototypeMethod(t, "get", Get);
+    Nan::SetPrototypeMethod(t, "run", Run);
+    Nan::SetPrototypeMethod(t, "all", All);
+    Nan::SetPrototypeMethod(t, "each", Each);
+    Nan::SetPrototypeMethod(t, "reset", Reset);
+    Nan::SetPrototypeMethod(t, "finalize", Finalize);
 
-    target->Set(String::NewSymbol("Statement"),
-        constructor_template->GetFunction());
+    constructor_template.Reset(t);
+    Nan::Set(target, Nan::New("Statement").ToLocalChecked(),
+        Nan::GetFunction(t).ToLocalChecked());
 }
 
 void Statement::Process() {
@@ -60,59 +60,56 @@ void Statement::Schedule(Work_Callback callback, Baton* baton) {
 }
 
 template <class T> void Statement::Error(T* baton) {
+    Nan::HandleScope scope;
+
     Statement* stmt = baton->stmt;
     // Fail hard on logic errors.
     assert(stmt->status != 0);
-    EXCEPTION(String::New(stmt->message.c_str()), stmt->status, exception);
+    EXCEPTION(Nan::New(stmt->message.c_str()).ToLocalChecked(), stmt->status, exception);
+
+    Local<Function> cb = Nan::New(baton->callback);
 
-    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
+    if (!cb.IsEmpty() && cb->IsFunction()) {
         Local<Value> argv[] = { exception };
-        TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
+        TRY_CATCH_CALL(stmt->handle(), cb, 1, argv);
     }
     else {
-        Local<Value> argv[] = { String::NewSymbol("error"), exception };
-        EMIT_EVENT(stmt->handle_, 2, argv);
+        Local<Value> argv[] = { Nan::New("error").ToLocalChecked(), exception };
+        EMIT_EVENT(stmt->handle(), 2, argv);
     }
 }
 
 // { Database db, String sql, Array params, Function callback }
-Handle<Value> Statement::New(const Arguments& args) {
-    HandleScope scope;
-
-    if (!args.IsConstructCall()) {
-        return ThrowException(Exception::TypeError(
-            String::New("Use the new operator to create new Statement objects"))
-        );
+NAN_METHOD(Statement::New) {
+    if (!info.IsConstructCall()) {
+        return Nan::ThrowTypeError("Use the new operator to create new Statement objects");
     }
 
-    int length = args.Length();
+    int length = info.Length();
 
-    if (length <= 0 || !Database::HasInstance(args[0])) {
-        return ThrowException(Exception::TypeError(
-            String::New("Database object expected")));
+    if (length <= 0 || !Database::HasInstance(info[0])) {
+        return Nan::ThrowTypeError("Database object expected");
     }
-    else if (length <= 1 || !args[1]->IsString()) {
-        return ThrowException(Exception::TypeError(
-            String::New("SQL query expected")));
+    else if (length <= 1 || !info[1]->IsString()) {
+        return Nan::ThrowTypeError("SQL query expected");
     }
-    else if (length > 2 && !args[2]->IsUndefined() && !args[2]->IsFunction()) {
-        return ThrowException(Exception::TypeError(
-            String::New("Callback expected")));
+    else if (length > 2 && !info[2]->IsUndefined() && !info[2]->IsFunction()) {
+        return Nan::ThrowTypeError("Callback expected");
     }
 
-    Database* db = ObjectWrap::Unwrap<Database>(args[0]->ToObject());
-    Local<String> sql = Local<String>::Cast(args[1]);
+    Database* db = Nan::ObjectWrap::Unwrap<Database>(info[0].As<Object>());
+    Local<String> sql = Local<String>::Cast(info[1]);
 
-    args.This()->Set(String::NewSymbol("sql"), sql, ReadOnly);
+    info.This()->ForceSet(Nan::New("sql").ToLocalChecked(), sql, ReadOnly);
 
     Statement* stmt = new Statement(db);
-    stmt->Wrap(args.This());
+    stmt->Wrap(info.This());
 
-    PrepareBaton* baton = new PrepareBaton(db, Local<Function>::Cast(args[2]), stmt);
-    baton->sql = std::string(*String::Utf8Value(sql));
+    PrepareBaton* baton = new PrepareBaton(db, Local<Function>::Cast(info[2]), stmt);
+    baton->sql = std::string(*Nan::Utf8String(sql));
     db->Schedule(Work_BeginPrepare, baton);
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
 void Statement::Work_BeginPrepare(Database::Baton* baton) {
@@ -128,27 +125,28 @@ void Statement::Work_Prepare(uv_work_t* req) {
 
     // In case preparing fails, we use a mutex to make sure we get the associated
     // error message.
-    sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->handle);
+    sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->_handle);
     sqlite3_mutex_enter(mtx);
 
     stmt->status = sqlite3_prepare_v2(
-        baton->db->handle,
+        baton->db->_handle,
         baton->sql.c_str(),
         baton->sql.size(),
-        &stmt->handle,
+        &stmt->_handle,
         NULL
     );
 
     if (stmt->status != SQLITE_OK) {
-        stmt->message = std::string(sqlite3_errmsg(baton->db->handle));
-        stmt->handle = NULL;
+        stmt->message = std::string(sqlite3_errmsg(baton->db->_handle));
+        stmt->_handle = NULL;
     }
 
     sqlite3_mutex_leave(mtx);
 }
 
 void Statement::Work_AfterPrepare(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     STATEMENT_INIT(PrepareBaton);
 
     if (stmt->status != SQLITE_OK) {
@@ -157,9 +155,10 @@ void Statement::Work_AfterPrepare(uv_work_t* req) {
     }
     else {
         stmt->prepared = true;
-        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-            Local<Value> argv[] = { Local<Value>::New(Null()) };
-            TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
+        Local<Function> cb = Nan::New(baton->callback);
+        if (!cb.IsEmpty() && cb->IsFunction()) {
+            Local<Value> argv[] = { Nan::Null() };
+            TRY_CATCH_CALL(stmt->handle(), cb, 1, argv);
         }
     }
 
@@ -167,75 +166,77 @@ void Statement::Work_AfterPrepare(uv_work_t* req) {
 }
 
 template <class T> Values::Field*
-                   Statement::BindParameter(const Handle<Value> source, T pos) {
+                   Statement::BindParameter(const Local<Value> source, T pos) {
     if (source->IsString() || source->IsRegExp()) {
-        String::Utf8Value val(source->ToString());
+        Nan::Utf8String val(source);
         return new Values::Text(pos, val.length(), *val);
     }
     else if (source->IsInt32()) {
-        return new Values::Integer(pos, source->Int32Value());
+        return new Values::Integer(pos, Nan::To<int32_t>(source).FromJust());
     }
     else if (source->IsNumber()) {
-        return new Values::Float(pos, source->NumberValue());
+        return new Values::Float(pos, Nan::To<double>(source).FromJust());
     }
     else if (source->IsBoolean()) {
-        return new Values::Integer(pos, source->BooleanValue() ? 1 : 0);
+        return new Values::Integer(pos, Nan::To<bool>(source).FromJust() ? 1 : 0);
     }
     else if (source->IsNull()) {
         return new Values::Null(pos);
     }
     else if (Buffer::HasInstance(source)) {
-        Local<Object> buffer = source->ToObject();
+        Local<Object> buffer = Nan::To<Object>(source).ToLocalChecked();
         return new Values::Blob(pos, Buffer::Length(buffer), Buffer::Data(buffer));
     }
     else if (source->IsDate()) {
-        return new Values::Float(pos, source->NumberValue());
+        return new Values::Float(pos, Nan::To<double>(source).FromJust());
     }
     else {
         return NULL;
     }
 }
 
-template <class T> T* Statement::Bind(const Arguments& args, int start, int last) {
-    if (last < 0) last = args.Length();
+template <class T> T* Statement::Bind(Nan::NAN_METHOD_ARGS_TYPE info, int start, int last) {
+    Nan::HandleScope scope;
+
+    if (last < 0) last = info.Length();
     Local<Function> callback;
-    if (last > start && args[last - 1]->IsFunction()) {
-        callback = Local<Function>::Cast(args[last - 1]);
+    if (last > start && info[last - 1]->IsFunction()) {
+        callback = Local<Function>::Cast(info[last - 1]);
         last--;
     }
 
     T* baton = new T(this, callback);
 
     if (start < last) {
-        if (args[start]->IsArray()) {
-            Local<Array> array = Local<Array>::Cast(args[start]);
+        if (info[start]->IsArray()) {
+            Local<Array> array = Local<Array>::Cast(info[start]);
             int length = array->Length();
             // Note: bind parameters start with 1.
             for (int i = 0, pos = 1; i < length; i++, pos++) {
-                baton->parameters.push_back(BindParameter(array->Get(i), pos));
+                baton->parameters.push_back(BindParameter(Nan::Get(array, i).ToLocalChecked(), pos));
             }
         }
-        else if (!args[start]->IsObject() || args[start]->IsRegExp() || args[start]->IsDate() || Buffer::HasInstance(args[start])) {
+        else if (!info[start]->IsObject() || info[start]->IsRegExp() || info[start]->IsDate() || Buffer::HasInstance(info[start])) {
             // Parameters directly in array.
             // Note: bind parameters start with 1.
             for (int i = start, pos = 1; i < last; i++, pos++) {
-                baton->parameters.push_back(BindParameter(args[i], pos));
+                baton->parameters.push_back(BindParameter(info[i], pos));
             }
         }
-        else if (args[start]->IsObject()) {
-            Local<Object> object = Local<Object>::Cast(args[start]);
-            Local<Array> array = object->GetPropertyNames();
+        else if (info[start]->IsObject()) {
+            Local<Object> object = Local<Object>::Cast(info[start]);
+            Local<Array> array = Nan::GetPropertyNames(object).ToLocalChecked();
             int length = array->Length();
             for (int i = 0; i < length; i++) {
-                Local<Value> name = array->Get(i);
+                Local<Value> name = Nan::Get(array, i).ToLocalChecked();
 
                 if (name->IsInt32()) {
                     baton->parameters.push_back(
-                        BindParameter(object->Get(name), name->Int32Value()));
+                        BindParameter(Nan::Get(object, name).ToLocalChecked(), Nan::To<int32_t>(name).FromJust()));
                 }
                 else {
-                    baton->parameters.push_back(BindParameter(object->Get(name),
-                        *String::Utf8Value(Local<String>::Cast(name))));
+                    baton->parameters.push_back(BindParameter(Nan::Get(object, name).ToLocalChecked(),
+                        *Nan::Utf8String(name)));
                 }
             }
         }
@@ -252,8 +253,8 @@ bool Statement::Bind(const Parameters & parameters) {
         return true;
     }
 
-    sqlite3_reset(handle);
-    sqlite3_clear_bindings(handle);
+    sqlite3_reset(_handle);
+    sqlite3_clear_bindings(_handle);
 
     Parameters::const_iterator it = parameters.begin();
     Parameters::const_iterator end = parameters.end();
@@ -267,54 +268,53 @@ bool Statement::Bind(const Parameters & parameters) {
                 pos = field->index;
             }
             else {
-                pos = sqlite3_bind_parameter_index(handle, field->name.c_str());
+                pos = sqlite3_bind_parameter_index(_handle, field->name.c_str());
             }
 
             switch (field->type) {
                 case SQLITE_INTEGER: {
-                    status = sqlite3_bind_int(handle, pos,
+                    status = sqlite3_bind_int(_handle, pos,
                         ((Values::Integer*)field)->value);
                 } break;
                 case SQLITE_FLOAT: {
-                    status = sqlite3_bind_double(handle, pos,
+                    status = sqlite3_bind_double(_handle, pos,
                         ((Values::Float*)field)->value);
                 } break;
                 case SQLITE_TEXT: {
-                    status = sqlite3_bind_text(handle, pos,
+                    status = sqlite3_bind_text(_handle, pos,
                         ((Values::Text*)field)->value.c_str(),
                         ((Values::Text*)field)->value.size(), SQLITE_TRANSIENT);
                 } break;
                 case SQLITE_BLOB: {
-                    status = sqlite3_bind_blob(handle, pos,
+                    status = sqlite3_bind_blob(_handle, pos,
                         ((Values::Blob*)field)->value,
                         ((Values::Blob*)field)->length, SQLITE_TRANSIENT);
                 } break;
                 case SQLITE_NULL: {
-                    status = sqlite3_bind_null(handle, pos);
+                    status = sqlite3_bind_null(_handle, pos);
                 } break;
             }
-        }
 
-        if (status != SQLITE_OK) {
-            message = std::string(sqlite3_errmsg(db->handle));
-            return false;
+            if (status != SQLITE_OK) {
+                message = std::string(sqlite3_errmsg(db->_handle));
+                return false;
+            }
         }
     }
 
     return true;
 }
 
-Handle<Value> Statement::Bind(const Arguments& args) {
-    HandleScope scope;
-    Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
+NAN_METHOD(Statement::Bind) {
+    Statement* stmt = Nan::ObjectWrap::Unwrap<Statement>(info.This());
 
-    Baton* baton = stmt->Bind<Baton>(args);
+    Baton* baton = stmt->Bind<Baton>(info);
     if (baton == NULL) {
-        return ThrowException(Exception::Error(String::New("Data type is not supported")));
+        return Nan::ThrowTypeError("Data type is not supported");
     }
     else {
         stmt->Schedule(Work_BeginBind, baton);
-        return args.This();
+        info.GetReturnValue().Set(info.This());
     }
 }
 
@@ -325,14 +325,15 @@ void Statement::Work_BeginBind(Baton* baton) {
 void Statement::Work_Bind(uv_work_t* req) {
     STATEMENT_INIT(Baton);
 
-    sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
+    sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
     sqlite3_mutex_enter(mtx);
     stmt->Bind(baton->parameters);
     sqlite3_mutex_leave(mtx);
 }
 
 void Statement::Work_AfterBind(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     STATEMENT_INIT(Baton);
 
     if (stmt->status != SQLITE_OK) {
@@ -340,9 +341,10 @@ void Statement::Work_AfterBind(uv_work_t* req) {
     }
     else {
         // Fire callbacks.
-        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-            Local<Value> argv[] = { Local<Value>::New(Null()) };
-            TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
+        Local<Function> cb = Nan::New(baton->callback);
+        if (!cb.IsEmpty() && cb->IsFunction()) {
+            Local<Value> argv[] = { Nan::Null() };
+            TRY_CATCH_CALL(stmt->handle(), cb, 1, argv);
         }
     }
 
@@ -351,17 +353,16 @@ void Statement::Work_AfterBind(uv_work_t* req) {
 
 
 
-Handle<Value> Statement::Get(const Arguments& args) {
-    HandleScope scope;
-    Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
+NAN_METHOD(Statement::Get) {
+    Statement* stmt = Nan::ObjectWrap::Unwrap<Statement>(info.This());
 
-    Baton* baton = stmt->Bind<RowBaton>(args);
+    Baton* baton = stmt->Bind<RowBaton>(info);
     if (baton == NULL) {
-        return ThrowException(Exception::Error(String::New("Data type is not supported")));
+        return Nan::ThrowError("Data type is not supported");
     }
     else {
         stmt->Schedule(Work_BeginGet, baton);
-        return args.This();
+        info.GetReturnValue().Set(info.This());
     }
 }
 
@@ -373,14 +374,14 @@ void Statement::Work_Get(uv_work_t* req) {
     STATEMENT_INIT(RowBaton);
 
     if (stmt->status != SQLITE_DONE || baton->parameters.size()) {
-        sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
+        sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
         sqlite3_mutex_enter(mtx);
 
         if (stmt->Bind(baton->parameters)) {
-            stmt->status = sqlite3_step(stmt->handle);
+            stmt->status = sqlite3_step(stmt->_handle);
 
             if (!(stmt->status == SQLITE_ROW || stmt->status == SQLITE_DONE)) {
-                stmt->message = std::string(sqlite3_errmsg(stmt->db->handle));
+                stmt->message = std::string(sqlite3_errmsg(stmt->db->_handle));
             }
         }
 
@@ -388,13 +389,14 @@ void Statement::Work_Get(uv_work_t* req) {
 
         if (stmt->status == SQLITE_ROW) {
             // Acquire one result row before returning.
-            GetRow(&baton->row, stmt->handle);
+            GetRow(&baton->row, stmt->_handle);
         }
     }
 }
 
 void Statement::Work_AfterGet(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     STATEMENT_INIT(RowBaton);
 
     if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) {
@@ -402,15 +404,16 @@ void Statement::Work_AfterGet(uv_work_t* req) {
     }
     else {
         // Fire callbacks.
-        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
+        Local<Function> cb = Nan::New(baton->callback);
+        if (!cb.IsEmpty() && cb->IsFunction()) {
             if (stmt->status == SQLITE_ROW) {
                 // Create the result array from the data we acquired.
-                Local<Value> argv[] = { Local<Value>::New(Null()), RowToJS(&baton->row) };
-                TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv);
+                Local<Value> argv[] = { Nan::Null(), RowToJS(&baton->row) };
+                TRY_CATCH_CALL(stmt->handle(), cb, 2, argv);
             }
             else {
-                Local<Value> argv[] = { Local<Value>::New(Null()) };
-                TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
+                Local<Value> argv[] = { Nan::Null() };
+                TRY_CATCH_CALL(stmt->handle(), cb, 1, argv);
             }
         }
     }
@@ -418,17 +421,16 @@ void Statement::Work_AfterGet(uv_work_t* req) {
     STATEMENT_END();
 }
 
-Handle<Value> Statement::Run(const Arguments& args) {
-    HandleScope scope;
-    Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
+NAN_METHOD(Statement::Run) {
+    Statement* stmt = Nan::ObjectWrap::Unwrap<Statement>(info.This());
 
-    Baton* baton = stmt->Bind<RunBaton>(args);
+    Baton* baton = stmt->Bind<RunBaton>(info);
     if (baton == NULL) {
-        return ThrowException(Exception::Error(String::New("Data type is not supported")));
+        return Nan::ThrowError("Data type is not supported");
     }
     else {
         stmt->Schedule(Work_BeginRun, baton);
-        return args.This();
+        info.GetReturnValue().Set(info.This());
     }
 }
 
@@ -439,23 +441,23 @@ void Statement::Work_BeginRun(Baton* baton) {
 void Statement::Work_Run(uv_work_t* req) {
     STATEMENT_INIT(RunBaton);
 
-    sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
+    sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
     sqlite3_mutex_enter(mtx);
 
     // Make sure that we also reset when there are no parameters.
     if (!baton->parameters.size()) {
-        sqlite3_reset(stmt->handle);
+        sqlite3_reset(stmt->_handle);
     }
 
     if (stmt->Bind(baton->parameters)) {
-        stmt->status = sqlite3_step(stmt->handle);
+        stmt->status = sqlite3_step(stmt->_handle);
 
         if (!(stmt->status == SQLITE_ROW || stmt->status == SQLITE_DONE)) {
-            stmt->message = std::string(sqlite3_errmsg(stmt->db->handle));
+            stmt->message = std::string(sqlite3_errmsg(stmt->db->_handle));
         }
         else {
-            baton->inserted_id = sqlite3_last_insert_rowid(stmt->db->handle);
-            baton->changes = sqlite3_changes(stmt->db->handle);
+            baton->inserted_id = sqlite3_last_insert_rowid(stmt->db->_handle);
+            baton->changes = sqlite3_changes(stmt->db->_handle);
         }
     }
 
@@ -463,7 +465,8 @@ void Statement::Work_Run(uv_work_t* req) {
 }
 
 void Statement::Work_AfterRun(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     STATEMENT_INIT(RunBaton);
 
     if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) {
@@ -471,29 +474,29 @@ void Statement::Work_AfterRun(uv_work_t* req) {
     }
     else {
         // Fire callbacks.
-        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-            stmt->handle_->Set(String::NewSymbol("lastID"), Local<Integer>(Integer::New(baton->inserted_id)));
-            stmt->handle_->Set(String::NewSymbol("changes"), Local<Integer>(Integer::New(baton->changes)));
+        Local<Function> cb = Nan::New(baton->callback);
+        if (!cb.IsEmpty() && cb->IsFunction()) {
+            Nan::Set(stmt->handle(), Nan::New("lastID").ToLocalChecked(), Nan::New<Number>(baton->inserted_id));
+            Nan::Set(stmt->handle(), Nan::New("changes").ToLocalChecked(), Nan::New(baton->changes));
 
-            Local<Value> argv[] = { Local<Value>::New(Null()) };
-            TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
+            Local<Value> argv[] = { Nan::Null() };
+            TRY_CATCH_CALL(stmt->handle(), cb, 1, argv);
         }
     }
 
     STATEMENT_END();
 }
 
-Handle<Value> Statement::All(const Arguments& args) {
-    HandleScope scope;
-    Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
+NAN_METHOD(Statement::All) {
+    Statement* stmt = Nan::ObjectWrap::Unwrap<Statement>(info.This());
 
-    Baton* baton = stmt->Bind<RowsBaton>(args);
+    Baton* baton = stmt->Bind<RowsBaton>(info);
     if (baton == NULL) {
-        return ThrowException(Exception::Error(String::New("Data type is not supported")));
+        return Nan::ThrowError("Data type is not supported");
     }
     else {
         stmt->Schedule(Work_BeginAll, baton);
-        return args.This();
+        info.GetReturnValue().Set(info.This());
     }
 }
 
@@ -504,23 +507,23 @@ void Statement::Work_BeginAll(Baton* baton) {
 void Statement::Work_All(uv_work_t* req) {
     STATEMENT_INIT(RowsBaton);
 
-    sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
+    sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
     sqlite3_mutex_enter(mtx);
 
     // Make sure that we also reset when there are no parameters.
     if (!baton->parameters.size()) {
-        sqlite3_reset(stmt->handle);
+        sqlite3_reset(stmt->_handle);
     }
 
     if (stmt->Bind(baton->parameters)) {
-        while ((stmt->status = sqlite3_step(stmt->handle)) == SQLITE_ROW) {
+        while ((stmt->status = sqlite3_step(stmt->_handle)) == SQLITE_ROW) {
             Row* row = new Row();
-            GetRow(row, stmt->handle);
+            GetRow(row, stmt->_handle);
             baton->rows.push_back(row);
         }
 
         if (stmt->status != SQLITE_DONE) {
-            stmt->message = std::string(sqlite3_errmsg(stmt->db->handle));
+            stmt->message = std::string(sqlite3_errmsg(stmt->db->_handle));
         }
     }
 
@@ -528,7 +531,8 @@ void Statement::Work_All(uv_work_t* req) {
 }
 
 void Statement::Work_AfterAll(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     STATEMENT_INIT(RowsBaton);
 
     if (stmt->status != SQLITE_DONE) {
@@ -536,27 +540,28 @@ void Statement::Work_AfterAll(uv_work_t* req) {
     }
     else {
         // Fire callbacks.
-        if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
+        Local<Function> cb = Nan::New(baton->callback);
+        if (!cb.IsEmpty() && cb->IsFunction()) {
             if (baton->rows.size()) {
                 // Create the result array from the data we acquired.
-                Local<Array> result(Array::New(baton->rows.size()));
+                Local<Array> result(Nan::New<Array>(baton->rows.size()));
                 Rows::const_iterator it = baton->rows.begin();
                 Rows::const_iterator end = baton->rows.end();
                 for (int i = 0; it < end; ++it, i++) {
-                    result->Set(i, RowToJS(*it));
+                    Nan::Set(result, i, RowToJS(*it));
                     delete *it;
                 }
 
-                Local<Value> argv[] = { Local<Value>::New(Null()), result };
-                TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv);
+                Local<Value> argv[] = { Nan::Null(), result };
+                TRY_CATCH_CALL(stmt->handle(), cb, 2, argv);
             }
             else {
                 // There were no result rows.
                 Local<Value> argv[] = {
-                    Local<Value>::New(Null()),
-                    Local<Value>::New(Array::New(0))
+                    Nan::Null(),
+                    Nan::New<Array>(0)
                 };
-                TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv);
+                TRY_CATCH_CALL(stmt->handle(), cb, 2, argv);
             }
         }
     }
@@ -564,25 +569,24 @@ void Statement::Work_AfterAll(uv_work_t* req) {
     STATEMENT_END();
 }
 
-Handle<Value> Statement::Each(const Arguments& args) {
-    HandleScope scope;
-    Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
+NAN_METHOD(Statement::Each) {
+    Statement* stmt = Nan::ObjectWrap::Unwrap<Statement>(info.This());
 
-    int last = args.Length();
+    int last = info.Length();
 
     Local<Function> completed;
-    if (last >= 2 && args[last - 1]->IsFunction() && args[last - 2]->IsFunction()) {
-        completed = Local<Function>::Cast(args[--last]);
+    if (last >= 2 && info[last - 1]->IsFunction() && info[last - 2]->IsFunction()) {
+        completed = Local<Function>::Cast(info[--last]);
     }
 
-    EachBaton* baton = stmt->Bind<EachBaton>(args, 0, last);
+    EachBaton* baton = stmt->Bind<EachBaton>(info, 0, last);
     if (baton == NULL) {
-        return ThrowException(Exception::Error(String::New("Data type is not supported")));
+        return Nan::ThrowError("Data type is not supported");
     }
     else {
-        baton->completed = Persistent<Function>::New(completed);
+        baton->completed.Reset(completed);
         stmt->Schedule(Work_BeginEach, baton);
-        return args.This();
+        info.GetReturnValue().Set(info.This());
     }
 }
 
@@ -590,9 +594,9 @@ void Statement::Work_BeginEach(Baton* baton) {
     // Only create the Async object when we're actually going into
     // the event loop. This prevents dangling events.
     EachBaton* each_baton = static_cast<EachBaton*>(baton);
-    each_baton->async = new Async(each_baton->stmt, AsyncEach);
-    each_baton->async->item_cb = Persistent<Function>::New(each_baton->callback);
-    each_baton->async->completed_cb = Persistent<Function>::New(each_baton->completed);
+    each_baton->async = new Async(each_baton->stmt, reinterpret_cast<uv_async_cb>(AsyncEach));
+    each_baton->async->item_cb.Reset(each_baton->callback);
+    each_baton->async->completed_cb.Reset(each_baton->completed);
 
     STATEMENT_BEGIN(Each);
 }
@@ -602,23 +606,23 @@ void Statement::Work_Each(uv_work_t* req) {
 
     Async* async = baton->async;
 
-    sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
+    sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->_handle);
 
     int retrieved = 0;
 
     // Make sure that we also reset when there are no parameters.
     if (!baton->parameters.size()) {
-        sqlite3_reset(stmt->handle);
+        sqlite3_reset(stmt->_handle);
     }
 
     if (stmt->Bind(baton->parameters)) {
         while (true) {
             sqlite3_mutex_enter(mtx);
-            stmt->status = sqlite3_step(stmt->handle);
+            stmt->status = sqlite3_step(stmt->_handle);
             if (stmt->status == SQLITE_ROW) {
                 sqlite3_mutex_leave(mtx);
                 Row* row = new Row();
-                GetRow(row, stmt->handle);
+                GetRow(row, stmt->_handle);
                 NODE_SQLITE3_MUTEX_LOCK(&async->mutex)
                 async->data.push_back(row);
                 retrieved++;
@@ -628,7 +632,7 @@ void Statement::Work_Each(uv_work_t* req) {
             }
             else {
                 if (stmt->status != SQLITE_DONE) {
-                    stmt->message = std::string(sqlite3_errmsg(stmt->db->handle));
+                    stmt->message = std::string(sqlite3_errmsg(stmt->db->_handle));
                 }
                 sqlite3_mutex_leave(mtx);
                 break;
@@ -648,7 +652,8 @@ void Statement::CloseCallback(uv_handle_t* handle) {
 }
 
 void Statement::AsyncEach(uv_async_t* handle, int status) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     Async* async = static_cast<Async*>(handle->data);
 
     while (true) {
@@ -662,36 +667,39 @@ void Statement::AsyncEach(uv_async_t* handle, int status) {
             break;
         }
 
-        if (!async->item_cb.IsEmpty() && async->item_cb->IsFunction()) {
+        Local<Function> cb = Nan::New(async->item_cb);
+        if (!cb.IsEmpty() && cb->IsFunction()) {
             Local<Value> argv[2];
-            argv[0] = Local<Value>::New(Null());
+            argv[0] = Nan::Null();
 
             Rows::const_iterator it = rows.begin();
             Rows::const_iterator end = rows.end();
             for (int i = 0; it < end; ++it, i++) {
                 argv[1] = RowToJS(*it);
                 async->retrieved++;
-                TRY_CATCH_CALL(async->stmt->handle_, async->item_cb, 2, argv);
+                TRY_CATCH_CALL(async->stmt->handle(), cb, 2, argv);
                 delete *it;
             }
         }
     }
 
+    Local<Function> cb = Nan::New(async->completed_cb);
     if (async->completed) {
-        if (!async->completed_cb.IsEmpty() &&
-                async->completed_cb->IsFunction()) {
+        if (!cb.IsEmpty() &&
+                cb->IsFunction()) {
             Local<Value> argv[] = {
-                Local<Value>::New(Null()),
-                Integer::New(async->retrieved)
+                Nan::Null(),
+                Nan::New(async->retrieved)
             };
-            TRY_CATCH_CALL(async->stmt->handle_, async->completed_cb, 2, argv);
+            TRY_CATCH_CALL(async->stmt->handle(), cb, 2, argv);
         }
-        uv_close((uv_handle_t*)handle, CloseCallback);
+        uv_close(reinterpret_cast<uv_handle_t*>(handle), CloseCallback);
     }
 }
 
 void Statement::Work_AfterEach(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     STATEMENT_INIT(EachBaton);
 
     if (stmt->status != SQLITE_DONE) {
@@ -701,16 +709,15 @@ void Statement::Work_AfterEach(uv_work_t* req) {
     STATEMENT_END();
 }
 
-Handle<Value> Statement::Reset(const Arguments& args) {
-    HandleScope scope;
-    Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
+NAN_METHOD(Statement::Reset) {
+    Statement* stmt = Nan::ObjectWrap::Unwrap<Statement>(info.This());
 
     OPTIONAL_ARGUMENT_FUNCTION(0, callback);
 
     Baton* baton = new Baton(stmt, callback);
     stmt->Schedule(Work_BeginReset, baton);
 
-    return args.This();
+    info.GetReturnValue().Set(info.This());
 }
 
 void Statement::Work_BeginReset(Baton* baton) {
@@ -720,25 +727,29 @@ void Statement::Work_BeginReset(Baton* baton) {
 void Statement::Work_Reset(uv_work_t* req) {
     STATEMENT_INIT(Baton);
 
-    sqlite3_reset(stmt->handle);
+    sqlite3_reset(stmt->_handle);
     stmt->status = SQLITE_OK;
 }
 
 void Statement::Work_AfterReset(uv_work_t* req) {
-    HandleScope scope;
+    Nan::HandleScope scope;
+
     STATEMENT_INIT(Baton);
 
     // Fire callbacks.
-    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-        Local<Value> argv[] = { Local<Value>::New(Null()) };
-        TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
+    Local<Function> cb = Nan::New(baton->callback);
+    if (!cb.IsEmpty() && cb->IsFunction()) {
+        Local<Value> argv[] = { Nan::Null() };
+        TRY_CATCH_CALL(stmt->handle(), cb, 1, argv);
     }
 
     STATEMENT_END();
 }
 
 Local<Object> Statement::RowToJS(Row* row) {
-    Local<Object> result(Object::New());
+    Nan::EscapableHandleScope scope;
+
+    Local<Object> result = Nan::New<Object>();
 
     Row::const_iterator it = row->begin();
     Row::const_iterator end = row->end();
@@ -749,32 +760,28 @@ Local<Object> Statement::RowToJS(Row* row) {
 
         switch (field->type) {
             case SQLITE_INTEGER: {
-                value = Local<Value>(Number::New(((Values::Integer*)field)->value));
+                value = Nan::New<Number>(((Values::Integer*)field)->value);
             } break;
             case SQLITE_FLOAT: {
-                value = Local<Value>(Number::New(((Values::Float*)field)->value));
+                value = Nan::New<Number>(((Values::Float*)field)->value);
             } break;
             case SQLITE_TEXT: {
-                value = Local<Value>(String::New(((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size()));
+                value = Nan::New<String>(((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size()).ToLocalChecked();
             } break;
             case SQLITE_BLOB: {
-#if NODE_VERSION_AT_LEAST(0, 11, 3)
-                value = Local<Value>::New(Buffer::New(((Values::Blob*)field)->value, ((Values::Blob*)field)->length));
-#else
-                value = Local<Value>::New(Buffer::New(((Values::Blob*)field)->value, ((Values::Blob*)field)->length)->handle_);
-#endif
+                value = Nan::CopyBuffer(((Values::Blob*)field)->value, ((Values::Blob*)field)->length).ToLocalChecked();
             } break;
             case SQLITE_NULL: {
-                value = Local<Value>::New(Null());
+                value = Nan::Null();
             } break;
         }
 
-        result->Set(String::NewSymbol(field->name.c_str()), value);
+        Nan::Set(result, Nan::New(field->name.c_str()).ToLocalChecked(), value);
 
         DELETE_FIELD(field);
     }
 
-    return result;
+    return scope.Escape(result);
 }
 
 void Statement::GetRow(Row* row, sqlite3_stmt* stmt) {
@@ -809,23 +816,25 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) {
     }
 }
 
-Handle<Value> Statement::Finalize(const Arguments& args) {
-    HandleScope scope;
-    Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
+NAN_METHOD(Statement::Finalize) {
+    Statement* stmt = Nan::ObjectWrap::Unwrap<Statement>(info.This());
     OPTIONAL_ARGUMENT_FUNCTION(0, callback);
 
     Baton* baton = new Baton(stmt, callback);
     stmt->Schedule(Finalize, baton);
 
-    return stmt->db->handle_;
+    info.GetReturnValue().Set(stmt->db->handle());
 }
 
 void Statement::Finalize(Baton* baton) {
+    Nan::HandleScope scope;
+
     baton->stmt->Finalize();
 
     // Fire callback in case there was one.
-    if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
-        TRY_CATCH_CALL(baton->stmt->handle_, baton->callback, 0, NULL);
+    Local<Function> cb = Nan::New(baton->callback);
+    if (!cb.IsEmpty() && cb->IsFunction()) {
+        TRY_CATCH_CALL(baton->stmt->handle(), cb, 0, NULL);
     }
 
     delete baton;
@@ -837,16 +846,18 @@ void Statement::Finalize() {
     CleanQueue();
     // Finalize returns the status code of the last operation. We already fired
     // error events in case those failed.
-    sqlite3_finalize(handle);
-    handle = NULL;
+    sqlite3_finalize(_handle);
+    _handle = NULL;
     db->Unref();
 }
 
 void Statement::CleanQueue() {
+    Nan::HandleScope scope;
+
     if (prepared && !queue.empty()) {
         // This statement has already been prepared and is now finalized.
         // Fire error for all remaining items in the queue.
-        EXCEPTION(String::New("Statement is already finalized"), SQLITE_MISUSE, exception);
+        EXCEPTION(Nan::New<String>("Statement is already finalized").ToLocalChecked(), SQLITE_MISUSE, exception);
         Local<Value> argv[] = { exception };
         bool called = false;
 
@@ -855,9 +866,11 @@ void Statement::CleanQueue() {
             Call* call = queue.front();
             queue.pop();
 
-            if (prepared && !call->baton->callback.IsEmpty() &&
-                call->baton->callback->IsFunction()) {
-                TRY_CATCH_CALL(handle_, call->baton->callback, 1, argv);
+            Local<Function> cb = Nan::New(call->baton->callback);
+
+            if (prepared && !cb.IsEmpty() &&
+                cb->IsFunction()) {
+                TRY_CATCH_CALL(handle(), cb, 1, argv);
                 called = true;
             }
 
@@ -870,8 +883,8 @@ void Statement::CleanQueue() {
         // When we couldn't call a callback function, emit an error on the
         // Statement object.
         if (!called) {
-            Local<Value> args[] = { String::NewSymbol("error"), exception };
-            EMIT_EVENT(handle_, 2, args);
+            Local<Value> info[] = { Nan::New("error").ToLocalChecked(), exception };
+            EMIT_EVENT(handle(), 2, info);
         }
     }
     else while (!queue.empty()) {
diff --git a/src/statement.h b/src/statement.h
index 3b02677..90d295b 100644
--- a/src/statement.h
+++ b/src/statement.h
@@ -1,7 +1,6 @@
 #ifndef NODE_SQLITE3_SRC_STATEMENT_H
 #define NODE_SQLITE3_SRC_STATEMENT_H
 
-#include <node.h>
 
 #include "database.h"
 #include "threading.h"
@@ -13,6 +12,7 @@
 #include <vector>
 
 #include <sqlite3.h>
+#include <nan.h>
 
 using namespace v8;
 using namespace node;
@@ -71,23 +71,23 @@ typedef Row Parameters;
 
 
 
-class Statement : public ObjectWrap {
+class Statement : public Nan::ObjectWrap {
 public:
-    static Persistent<FunctionTemplate> constructor_template;
+    static Nan::Persistent<FunctionTemplate> constructor_template;
 
-    static void Init(Handle<Object> target);
-    static Handle<Value> New(const Arguments& args);
+    static NAN_MODULE_INIT(Init);
+    static NAN_METHOD(New);
 
     struct Baton {
         uv_work_t request;
         Statement* stmt;
-        Persistent<Function> callback;
+        Nan::Persistent<Function> callback;
         Parameters parameters;
 
-        Baton(Statement* stmt_, Handle<Function> cb_) : stmt(stmt_) {
+        Baton(Statement* stmt_, Local<Function> cb_) : stmt(stmt_) {
             stmt->Ref();
             request.data = this;
-            callback = Persistent<Function>::New(cb_);
+            callback.Reset(cb_);
         }
         virtual ~Baton() {
             for (unsigned int i = 0; i < parameters.size(); i++) {
@@ -95,25 +95,25 @@ public:
                 DELETE_FIELD(field);
             }
             stmt->Unref();
-            callback.Dispose();
+            callback.Reset();
         }
     };
 
     struct RowBaton : Baton {
-        RowBaton(Statement* stmt_, Handle<Function> cb_) :
+        RowBaton(Statement* stmt_, Local<Function> cb_) :
             Baton(stmt_, cb_) {}
         Row row;
     };
 
     struct RunBaton : Baton {
-        RunBaton(Statement* stmt_, Handle<Function> cb_) :
+        RunBaton(Statement* stmt_, Local<Function> cb_) :
             Baton(stmt_, cb_), inserted_id(0), changes(0) {}
         sqlite3_int64 inserted_id;
         int changes;
     };
 
     struct RowsBaton : Baton {
-        RowsBaton(Statement* stmt_, Handle<Function> cb_) :
+        RowsBaton(Statement* stmt_, Local<Function> cb_) :
             Baton(stmt_, cb_) {}
         Rows rows;
     };
@@ -121,16 +121,20 @@ public:
     struct Async;
 
     struct EachBaton : Baton {
-        EachBaton(Statement* stmt_, Handle<Function> cb_) :
-            Baton(stmt_, cb_) {}
-        Persistent<Function> completed;
+        Nan::Persistent<Function> completed;
         Async* async; // Isn't deleted when the baton is deleted.
+
+        EachBaton(Statement* stmt_, Local<Function> cb_) :
+            Baton(stmt_, cb_) {}
+        virtual ~EachBaton() {
+            completed.Reset();
+        }
     };
 
     struct PrepareBaton : Database::Baton {
         Statement* stmt;
         std::string sql;
-        PrepareBaton(Database* db_, Handle<Function> cb_, Statement* stmt_) :
+        PrepareBaton(Database* db_, Local<Function> cb_, Statement* stmt_) :
             Baton(db_, cb_), stmt(stmt_) {
             stmt->Ref();
         }
@@ -162,8 +166,8 @@ public:
 
         // Store the callbacks here because we don't have
         // access to the baton in the async callback.
-        Persistent<Function> item_cb;
-        Persistent<Function> completed_cb;
+        Nan::Persistent<Function> item_cb;
+        Nan::Persistent<Function> completed_cb;
 
         Async(Statement* st, uv_async_cb async_cb) :
                 stmt(st), completed(false), retrieved(0) {
@@ -175,15 +179,15 @@ public:
 
         ~Async() {
             stmt->Unref();
-            item_cb.Dispose();
-            completed_cb.Dispose();
+            item_cb.Reset();
+            completed_cb.Reset();
             NODE_SQLITE3_MUTEX_DESTROY
         }
     };
 
-    Statement(Database* db_) : ObjectWrap(),
+    Statement(Database* db_) : Nan::ObjectWrap(),
             db(db_),
-            handle(NULL),
+            _handle(NULL),
             status(SQLITE_OK),
             prepared(false),
             locked(true),
@@ -202,7 +206,7 @@ public:
     WORK_DEFINITION(Each);
     WORK_DEFINITION(Reset);
 
-    static Handle<Value> Finalize(const Arguments& args);
+    static NAN_METHOD(Finalize);
 
 protected:
     static void Work_BeginPrepare(Database::Baton* baton);
@@ -215,9 +219,9 @@ protected:
     static void Finalize(Baton* baton);
     void Finalize();
 
-    template <class T> inline Values::Field* BindParameter(const Handle<Value> source, T pos);
-    template <class T> T* Bind(const Arguments& args, int start = 0, int end = -1);
-    bool Bind(const Parameters & parameters);
+    template <class T> inline Values::Field* BindParameter(const Local<Value> source, T pos);
+    template <class T> T* Bind(Nan::NAN_METHOD_ARGS_TYPE info, int start = 0, int end = -1);
+    bool Bind(const Parameters &parameters);
 
     static void GetRow(Row* row, sqlite3_stmt* stmt);
     static Local<Object> RowToJS(Row* row);
@@ -229,7 +233,7 @@ protected:
 protected:
     Database* db;
 
-    sqlite3_stmt* handle;
+    sqlite3_stmt* _handle;
     int status;
     std::string message;
 
diff --git a/test/json.test.js b/test/json.test.js
new file mode 100644
index 0000000..6d7d32d
--- /dev/null
+++ b/test/json.test.js
@@ -0,0 +1,22 @@
+var sqlite3 = require('..');
+
+if( process.env.NODE_SQLITE3_JSON1 === 'no' ){
+    describe('json', function() {
+        it(
+            'skips JSON tests when --sqlite=/usr (or similar) is tested',
+            function(){}
+        );
+    });
+} else {
+    describe('json', function() {
+        var db;
+
+        before(function(done) {
+            db = new sqlite3.Database(':memory:', done);
+        });
+
+        it('should select JSON', function(done) {
+            db.run('SELECT json(?)', JSON.stringify({ok:true}), done);
+        });
+    });
+}
diff --git a/test/named_columns.test.js b/test/named_columns.test.js
index fcb8f2c..9973bfc 100644
--- a/test/named_columns.test.js
+++ b/test/named_columns.test.js
@@ -26,4 +26,13 @@ describe('named columns', function() {
             done();
         });
     });
+
+    it('should be able to retrieve rowid of last inserted value', function(done) {
+        db.get("SELECT last_insert_rowid() as last_id FROM foo", function(err, row) {
+            if (err) throw err;
+            assert.equal(row.last_id, 1);
+            done();
+        });
+    });
+
 });
diff --git a/test/nw/Makefile b/test/nw/Makefile
index adb7dbf..9c82233 100755
--- a/test/nw/Makefile
+++ b/test/nw/Makefile
@@ -3,10 +3,10 @@ NODE_WEBKIT_VERSION=0.8.4
 all: app.nw
 
 node_modules/sqlite3:
-	npm install https://github.com/mapbox/node-sqlite3/tarball/master
+	npm install https://github.com/mapbox/node-sqlite3/tarball/master --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION)
 
-node_modules/sqlite3/lib/node_sqlite3.node: node_modules/sqlite3
-	cd node_modules/sqlite3 && nw-gyp rebuild --target=$(NODE_WEBKIT_VERSION) && rm -rf build/
+rebuild:
+	cd node_modules/sqlite3 && ./node_modules/.bin/node-pre-gyp rebuild --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION)
 
 node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip:
 	wget https://s3.amazonaws.com/node-webkit/v$(NODE_WEBKIT_VERSION)/node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip
@@ -14,7 +14,7 @@ node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip:
 ./node-webkit.app: node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip
 	unzip -o node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip
 
-app.nw: ./node-webkit.app Makefile package.json index.html node_modules/sqlite3/lib/node_sqlite3.node
+app.nw: ./node-webkit.app Makefile package.json index.html node_modules/sqlite3
 	zip app.nw index.html package.json node_modules
 
 test: ./node-webkit.app app.nw
@@ -30,8 +30,7 @@ package: ./node-webkit.app Makefile package.json index.html node_modules/sqlite3
 	./node-sqlite-test.app/Contents/MacOS/node-webkit
 
 clean:
-	rm -rf ./node_modules/sqlite3/build
-	rm -f ./node_modules/sqlite3/lib/node_sqlite3.node
+	rm -rf ./node_modules/sqlite3
 	rm -f ./app.nw
 	rm -rf node-sqlite-test.app
 	rm -f credits.html
diff --git a/test/prepare.test.js b/test/prepare.test.js
index eb9889e..c32db72 100644
--- a/test/prepare.test.js
+++ b/test/prepare.test.js
@@ -99,6 +99,57 @@ describe('prepare', function() {
         after(function(done) { db.close(done); });
     });
 
+    describe('inserting with accidental undefined', function() {
+        var db;
+        before(function(done) { db = new sqlite3.Database(':memory:', done); });
+
+        var inserted = 0;
+        var retrieved = 0;
+
+        it('should create the table', function(done) {
+            db.prepare("CREATE TABLE foo (num int)").run().finalize(done);
+        });
+
+        it('should insert two rows', function(done) {
+            db.prepare('INSERT INTO foo VALUES(4)').run(function(err) {
+                if (err) throw err;
+                inserted++;
+            }).run(undefined, function (err) {
+                // The second time we pass undefined as a parameter. This is
+                // a mistake, but it should either throw an error or be ignored,
+                // not silently fail to run the statement.
+                if (err) throw err;
+                inserted++;
+            }).finalize(function(err) {
+                if (err) throw err;
+                if (inserted == 2) done();
+            });
+        });
+
+        it('should retrieve the data', function(done) {
+            var stmt = db.prepare("SELECT num FROM foo", function(err) {
+                if (err) throw err;
+            });
+
+            for (var i = 0; i < 2; i++) (function(i) {
+                stmt.get(function(err, row) {
+                    if (err) throw err;
+                    assert(row);
+                    assert.equal(row.num, 4);
+                    retrieved++;
+                });
+            })(i);
+
+            stmt.finalize(done);
+        });
+
+        it('should have retrieved two rows', function() {
+            assert.equal(2, retrieved, "Didn't retrieve all rows");
+        });
+
+        after(function(done) { db.close(done); });
+    });
+
     describe('retrieving reset() function', function() {
         var db;
         before(function(done) { db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY, done); });
diff --git a/test/profile.test.js b/test/profile.test.js
index 5dc29b4..6545f09 100644
--- a/test/profile.test.js
+++ b/test/profile.test.js
@@ -14,6 +14,7 @@ describe('profiling', function() {
             if (sql.match(/^SELECT/)) {
                 assert.ok(!select);
                 assert.equal(sql, "SELECT * FROM foo");
+                console.log('profile select');
                 select = true;
             }
             else if (sql.match(/^CREATE/)) {
@@ -31,7 +32,7 @@ describe('profiling', function() {
         assert.ok(!create);
         db.run("CREATE TABLE foo (id int)", function(err) {
             if (err) throw err;
-            process.nextTick(function() {
+            setImmediate(function() {
                 assert.ok(create);
                 done();
             });
@@ -43,10 +44,10 @@ describe('profiling', function() {
         assert.ok(!select);
         db.run("SELECT * FROM foo", function(err) {
             if (err) throw err;
-            process.nextTick(function() {
+            setImmediate(function() {
                 assert.ok(select);
                 done();
-            });
+            }, 0);
         });
     });
 
diff --git a/test/unicode.test.js b/test/unicode.test.js
index 179431a..b76ca42 100644
--- a/test/unicode.test.js
+++ b/test/unicode.test.js
@@ -1,18 +1,73 @@
 var sqlite3 = require('..');
 var assert = require('assert');
 
-function randomString() {
-    var str = '';
-    for (var i = Math.random() * 300; i > 0; i--) {
-        str += String.fromCharCode(Math.floor(Math.random() * 65536));
-    }
-    return str;
-}
-
 describe('unicode', function() {
-    var db;
+    var first_values = [],
+        trailing_values = [],
+        chars = [],
+        subranges = new Array(2),
+        len = subranges.length,
+        db,
+        i;
+
     before(function(done) { db = new sqlite3.Database(':memory:', done); });
 
+    for (i = 0x20; i < 0x80; i++) {
+        first_values.push(i);
+    }
+
+    for (i = 0xc2; i < 0xf0; i++) {
+        first_values.push(i);
+    }
+
+    for (i = 0x80; i < 0xc0; i++) {
+        trailing_values.push(i);
+    }
+
+    for (i = 0; i < len; i++) {
+        subranges[i] = [];
+    }
+
+    for (i = 0xa0; i < 0xc0; i++) {
+        subranges[0].push(i);
+    }
+
+    for (i = 0x80; i < 0xa0; i++) {
+        subranges[1].push(i);
+    }
+
+    function random_choice(arr) {
+        return arr[Math.random() * arr.length | 0];
+    }
+
+    function random_utf8() {
+        var first = random_choice(first_values);
+
+        if (first < 0x80) {
+            return String.fromCharCode(first);
+        } else if (first < 0xe0) {
+            return String.fromCharCode((first & 0x1f) << 0x6 | random_choice(trailing_values) & 0x3f);
+        } else if (first == 0xe0) {
+             return String.fromCharCode(((first & 0xf) << 0xc) | ((random_choice(subranges[0]) & 0x3f) << 6) | random_choice(trailing_values) & 0x3f);
+        } else if (first == 0xed) {
+            return String.fromCharCode(((first & 0xf) << 0xc) | ((random_choice(subranges[1]) & 0x3f) << 6) | random_choice(trailing_values) & 0x3f);
+        } else if (first < 0xf0) {
+            return String.fromCharCode(((first & 0xf) << 0xc) | ((random_choice(trailing_values) & 0x3f) << 6) | random_choice(trailing_values) & 0x3f);
+        }
+    }
+
+    function randomString() {
+        var str = '',
+        i;
+
+        for (i = Math.random() * 300; i > 0; i--) {
+            str += random_utf8();
+        }
+
+        return str;
+    }
+
+
         // Generate random data.
     var data = [];
     var length = Math.floor(Math.random() * 1000) + 200;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/node-sqlite3.git



More information about the Pkg-javascript-commits mailing list