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

Jérémy Lal kapouer at moszumanska.debian.org
Wed Dec 21 10:42:25 UTC 2016


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

kapouer pushed a commit to annotated tag upstream/3.1.3+ds
in repository node-sqlite3.

commit 55cca3abdaeb8b91f90f7982be9d2440a0b683e2
Author: Jérémy Lal <kapouer at melix.org>
Date:   Wed Apr 13 02:04:53 2016 +0200

    Imported Upstream version 3.1.3+ds
---
 .gitignore                           |   7 +-
 .npmignore                           |  12 +
 .travis.yml                          | 121 +++++++++-
 CHANGELOG.md                         | 167 ++++++++++++-
 CONTRIBUTING.md                      |  57 +++++
 LICENSE                              |  33 +--
 Makefile                             |  50 +++-
 README.md                            | 153 +++++++-----
 appveyor.yml                         |  56 +++++
 binding.gyp                          |  80 +++----
 configure                            |   3 -
 deps/common-sqlite.gypi              |  55 ++++-
 deps/sqlite3.gyp                     |  12 +-
 lib/sqlite3.js                       | 114 ++++-----
 package.json                         |  51 ++--
 scripts/build-appveyor.bat           | 160 +++++++++++++
 scripts/build-local.bat              |  59 +++++
 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                       |  64 ++---
 src/gcc-preinclude.h                 |   6 +
 src/macros.h                         | 105 ++++----
 src/node_sqlite3.cc                  |   9 +-
 src/statement.cc                     | 451 ++++++++++++++++++-----------------
 src/statement.h                      |  58 ++---
 test/issue-108.test.js               |  28 +++
 test/json.test.js                    |  22 ++
 test/named_columns.test.js           |   9 +
 test/nw/.gitignore                   |   3 +
 test/nw/Makefile                     |  39 +++
 test/nw/index.html                   |  14 ++
 test/nw/package.json                 |   9 +
 test/prepare.test.js                 |  51 ++++
 test/profile.test.js                 |   7 +-
 test/unicode.test.js                 |  73 +++++-
 40 files changed, 1978 insertions(+), 739 deletions(-)

diff --git a/.gitignore b/.gitignore
index 57aa6de..1197bbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,10 @@
-.lock-wscript
 *.dylib
 *.so
 *.o
 *.lo
 *.Makefile
 *.target.gyp.mk
+lib/binding
 build
 out
 Release
@@ -16,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 c248402..64d73b7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,115 @@
-language: node_js
-node_js:
-  - "0.10"
-  - "0.8"
-  - "0.6"
-before_script: "npm install mocha"
+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:
+  global:
+    - JOBS: "8"
+    - secure: PifMOSnn+mWR1RUptXse+fLvWiTrzg0R/mazO7RWhXHWBKv0uAJ/qV3dI0GIRBLtjG10Iy+tT5RNh1TIbBzB9Y67wMcGvylUPG1+3EOKoBMEPnOD9AgCEQw4SOXfGPx0cq2N6ueSKieCgu1yKN9Wq7XCbE+zTk/DiRNIdLirVoo=
+    - secure: cc4esJY1vPXL31IeumAJoKWDDO2BTGFiltwfO1jbTbiV7QT911QUjTUasxXIVpOaHNCpxSTyevPwwTWfzt2EtF92Lli+qhQ2bbzMiDSBZstSrHdAe62Ai2M1oYYUwk/0cABB/2nO9uRyYwITCxpTSNzZBrYhn3C29WqBhPeVDmM=
+
+before_install:
+- 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:
+# put node-pre-gyp on path
+- export PATH=./node_modules/.bin/:$PATH
+
+before_script:
+# 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:
+- 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 08a58de..3cd2f9f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,170 @@
-# 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
+
+Released October 31st, 2013
+
+ - Started respecting `process.env.npm_config_tmp` as location to download binaries
+ - Removed uneeded `progress` dependency
+
+## 2.1.18
+
+Released October 22nd, 2013
+
+ - `node-sqlite3` moved to mapbox github group
+ - Fixed reporting of node-gyp errors
+ - Fixed support for node v0.6.x
+
+## 2.1.17
+ - Minor fixes to binary deployment
+
+## 2.1.16
+ - Support for binary deployment
 
 ## 2.1.15
 
 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/LICENSE b/LICENSE
index 2e4eba8..6c4ce40 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,24 +1,25 @@
-Copyright (c) 2011, Konstantin Käfer <kkaefer at gmail.com>
+Copyright (c) MapBox
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright notice,
-      this list of conditions and the following disclaimer in the documentation
-      and/or other materials provided with the distribution.
-    * Neither the name of "Development Seed" nor the names of its contributors
-      may be used to endorse or promote products derived from this software
-      without specific prior written permission.
+
+- Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or
+  other materials provided with the distribution.
+- Neither the name "MapBox" nor the names of its contributors may be
+  used to endorse or promote products derived from this software without
+  specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL Konstantin Käfer BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 7924cdd..56fcb27 100644
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,46 @@
-build:
-	node-gyp 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 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 486fd26..6f755fd 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,26 @@
-# 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/developmentseed/node-sqlite3.png?branch=master)](https://travis-ci.org/developmentseed/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.
 
-**Note:**   the module must be [installed](#installing) before use.
+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.
 
 ``` js
 var sqlite3 = require('sqlite3').verbose();
@@ -33,93 +43,122 @@ db.serialize(function() {
 db.close();
 ```
 
+# Features
 
-
-# FEATURES
-
-* Straightforward query and parameter binding interface
-* Full Buffer/Blob support
-* Extensive [debugging support](https://github.com/developmentseed/node-sqlite3/wiki/Debugging)
-* [Query serialization](https://github.com/developmentseed/node-sqlite3/wiki/Control-Flow) API
-* [Extension support](https://github.com/developmentseed/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
 
-See the [API documentation](https://github.com/developmentseed/node-sqlite3/wiki) in the wiki.
+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:
 
 * The latest `sqlite3` package: `npm install sqlite3`
 
-* GitHub's `master` branch: `npm install https://github.com/developmentseed/node-sqlite3/tarball/master`
+* 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
 
-# REBUILDING FOR NODE-WEBKIT
+    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:
 
-Because of ABI differences, only a rebuilt version of `sqlite3` can be used in [node-webkit](https://github.com/rogerwang/node-webkit).
+    npm install --build-from-source --sqlite=/usr/local/opt/sqlite/
 
-After the `sqlite3` module is installed (according to the previous section), do the following:
+## Building for 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).
+
+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: `nw-gyp rebuild --target=0.6.2`
+2. Build the module with the custom flags of `--runtime`, `--target_arch`, and `--target`:
 
-Remember the following:
+```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)
+```
 
-* 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).
+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.
 
-* After the `sqlite3` package is rebuilt 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.
+You can also run this command from within a `node-sqlite3` checkout:
 
-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.
+```sh
+npm install --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION)
+```
 
+Remember the following:
 
-# BUILDING FROM THE SOURCE
+* 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).
 
-Unless building via `npm install` (which uses its own `node-gyp`) you will need `node-gyp` installed globally:
+* 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.
 
-    npm install node-gyp -g
+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.
 
-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.
+## Building for sqlcipher
 
-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.
+For instructions for building sqlcipher see
+[Building SQLCipher for node.js](https://coolaj86.com/articles/building-sqlcipher-for-node-js-on-raspberry-pi-2/)
 
-    ./configure --sqlite=/usr/local
-    make
+To run node-sqlite3 against sqlcipher you need to compile from source by passing build options like:
 
-Or, using the node-gyp directly:
+    npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/
+    
+    node -e 'require("sqlite3")'
 
-     node-gyp --sqlite=/usr/local
-     make
+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:
 
-Or, using npm:
+### On OS X with Homebrew
 
-     npm install --sqlite=/usr/local
+Set the location where `brew` installed it:
 
-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.
+    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")'
 
-Note, if building against homebrew-installed sqlite on OS X you can do:
+### On most Linuxes (including Raspberry Pi)
 
-    ./configure --sqlite=/usr/local/opt/sqlite/
-    make
+Set the location where `make` installed it:
 
+    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")'
 
-# TESTING
+# Testing
 
 [mocha](https://github.com/visionmedia/mocha) is required to run unit tests.
 
@@ -129,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)
@@ -147,16 +185,15 @@ 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
 [Ryan Dahl](https://github.com/ry) for their SQLite bindings for node, and to mraleph on Freenode's #v8 for answering questions.
 
-Development of this module is sponsored by [Development Seed](http://developmentseed.org/).
+Development of this module is sponsored by [MapBox](http://mapbox.org/).
 
 
-# LICENSE
+# License
 
-`node-sqlite3` is [BSD licensed](https://github.com/developmentseed/node-sqlite3/raw/master/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 12a3704..a0c5faa 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -1,58 +1,52 @@
 {
-  'includes': [ 'deps/common-sqlite.gypi' ],
-  'variables': {
-      'sqlite%':'internal',
+  "includes": [ "deps/common-sqlite.gypi" ],
+  "variables": {
+      "sqlite%":"internal",
+      "sqlite_libname%":"sqlite3"
   },
-  'conditions': [
-      ['OS=="win"', {
-        'variables': {
-          'copy_command%': 'copy',
-        },
-      },{
-        'variables': {
-          'copy_command%': 'cp',
-        },
-      }]
-  ],
-  'targets': [
+  "targets": [
     {
-      'target_name': 'node_sqlite3',
-      'conditions': [
-        ['sqlite != "internal"', {
-            'libraries': [
-               '-L<@(sqlite)/lib',
-               '-lsqlite3'
+      "target_name": "<(module_name)",
+      "include_dirs": ["<!(node -e \"require('nan')\")"],
+      "conditions": [
+        ["sqlite != 'internal'", {
+            "include_dirs": [ "<(sqlite)/include" ],
+            "libraries": [
+               "-l<(sqlite_libname)"
             ],
-            'include_dirs': [ '<@(sqlite)/include' ]
+            "conditions": [ [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<@(sqlite)/lib"]} ] ],
+            "conditions": [ [ "OS!='win'", {"libraries+":["-L<@(sqlite)/lib"]} ] ],
+            'msvs_settings': {
+              'VCLinkerTool': {
+                'AdditionalLibraryDirectories': [
+                  '<(sqlite)/lib'
+                ],
+              },
+            }
         },
         {
-            'dependencies': [
-              'deps/sqlite3.gyp:sqlite3'
+            "dependencies": [
+              "deps/sqlite3.gyp:sqlite3"
             ]
         }
         ]
       ],
-      'sources': [
-        'src/database.cc',
-        'src/node_sqlite3.cc',
-        'src/statement.cc'
-      ],
+      "cflags": [ "-include ../src/gcc-preinclude.h" ],
+      "sources": [
+        "src/database.cc",
+        "src/node_sqlite3.cc",
+        "src/statement.cc"
+      ]
     },
     {
-      'target_name': 'action_after_build',
-      'type': 'none',
-      'dependencies': [ 'node_sqlite3' ],
-      'actions': [
-        {
-          'action_name': 'move_node_module',
-          'inputs': [
-            '<@(PRODUCT_DIR)/node_sqlite3.node'
-          ],
-          'outputs': [
-            'lib/node_sqlite3.node'
-          ],
-          'action': ['<@(copy_command)', '<@(PRODUCT_DIR)/node_sqlite3.node', 'lib/node_sqlite3.node']
-        }
+      "target_name": "action_after_build",
+      "type": "none",
+      "dependencies": [ "<(module_name)" ],
+      "copies": [
+          {
+            "files": [ "<(PRODUCT_DIR)/<(module_name).node" ],
+            "destination": "<(module_path)"
+          }
       ]
     }
   ]
diff --git a/configure b/configure
deleted file mode 100755
index 17af137..0000000
--- a/configure
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-node-gyp configure $@
diff --git a/deps/common-sqlite.gypi b/deps/common-sqlite.gypi
index 93134c2..1148aa6 100644
--- a/deps/common-sqlite.gypi
+++ b/deps/common-sqlite.gypi
@@ -1,5 +1,56 @@
 {
   'variables': {
-      'sqlite_version%':'3071700'
+      '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 48e5879..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,13 +80,19 @@
         'defines': [
           'SQLITE_THREADSAFE=1',
           'SQLITE_ENABLE_FTS3',
+          'SQLITE_ENABLE_JSON1',
           'SQLITE_ENABLE_RTREE'
         ],
       },
+      'cflags_cc': [
+          '-Wno-unused-value',
+          '-include ../src/gcc-preinclude.h'
+      ],
       'defines': [
         '_REENTRANT=1',
         'SQLITE_THREADSAFE=1',
         'SQLITE_ENABLE_FTS3',
+        'SQLITE_ENABLE_JSON1',
         'SQLITE_ENABLE_RTREE'
       ],
       'export_dependent_settings': [
diff --git a/lib/sqlite3.js b/lib/sqlite3.js
index 62541cf..466b902 100644
--- a/lib/sqlite3.js
+++ b/lib/sqlite3.js
@@ -1,12 +1,24 @@
-var sqlite3 = module.exports = exports = require('./node_sqlite3.node');
+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);
     }
 }
 
@@ -22,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);
@@ -53,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);
@@ -162,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 af7f054..dc226b3 100644
--- a/package.json
+++ b/package.json
@@ -1,41 +1,64 @@
 {
     "name": "sqlite3",
     "description": "Asynchronous, non-blocking SQLite3 bindings",
-    "version": "2.1.15",
-    "homepage": "http://github.com/developmentseed/node-sqlite3",
+    "version": "3.1.3",
+    "homepage": "http://github.com/mapbox/node-sqlite3",
     "author": {
-        "name": "Development Seed",
-        "url": "http://developmentseed.org/",
-        "email": "info at developmentseed.org"
+        "name": "MapBox",
+        "url": "https://mapbox.com/"
+    },
+    "binary": {
+        "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>",
-        "Dane Springmeyer <dane at developmentseed.org>",
-        "Will White <will at developmentseed.org>",
+        "Dane Springmeyer <dane at mapbox.com>",
+        "Will White <will at mapbox.com>",
         "Orlando Vazquez <ovazquez at gmail.com>",
         "Artem Kustikov <kustikoff at gmail.com>",
         "Eric Fredricksen <efredricksen at gmail.com>",
         "John Wright <mrjjwright at gmail.com>",
         "Ryan Dahl <ry at tinyclouds.org>",
-        "Tom MacWright <tom at developmentseed.org>",
+        "Tom MacWright <tom at mapbox.com>",
         "Carter Thaxton <carter.thaxton at gmail.com>",
         "Audrius Kažukauskas <audrius at neutrino.lt>",
         "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/developmentseed/node-sqlite3.git"
+        "url": "git://github.com/mapbox/node-sqlite3.git"
+    },
+    "dependencies": {
+        "nan": "~2.2.0",
+        "node-pre-gyp": "~0.6.25"
     },
-    "engines": {
-        "node": ">= 0.6.13 && < 0.11.0"
+    "bundledDependencies": [
+        "node-pre-gyp"
+    ],
+    "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"
 }
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_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 b2e4853..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,56 +100,56 @@ public:
     friend class Statement;
 
 protected:
-    Database() : ObjectWrap(),
-        handle(NULL),
+    Database() : Nan::ObjectWrap(),
+        _handle(NULL),
         open(false),
         locked(false),
         pending(0),
         serialize(false),
         debug_trace(NULL),
-        debug_profile(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);
 
@@ -166,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
new file mode 100644
index 0000000..38c9138
--- /dev/null
+++ b/src/gcc-preinclude.h
@@ -0,0 +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 1ed3de4..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()) {
+        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)));
                 }
             }
         }
@@ -247,13 +248,13 @@ template <class T> T* Statement::Bind(const Arguments& args, int start, int last
     return baton;
 }
 
-bool Statement::Bind(const Parameters parameters) {
+bool Statement::Bind(const Parameters & parameters) {
     if (parameters.size() == 0) {
         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 0b6e60c..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/issue-108.test.js b/test/issue-108.test.js
new file mode 100644
index 0000000..2ea69a3
--- /dev/null
+++ b/test/issue-108.test.js
@@ -0,0 +1,28 @@
+var sqlite3 = require('..'),
+    assert = require('assert');
+
+describe('buffer', function() {
+    var db;
+    // before(function() {
+    // });
+
+    it('should insert blobs', function(done) {
+        db = new sqlite3.Database(':memory:');
+        db.serialize(function () {
+
+            db.run("CREATE TABLE lorem (info BLOB)");
+            var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
+
+            stmt.on('error', function (err) {
+                throw err;
+            });
+
+            var buff = new Buffer(2);
+            stmt.run('a');
+            stmt.finalize();
+        });
+
+        db.close(done);
+
+    });
+});
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/.gitignore b/test/nw/.gitignore
new file mode 100644
index 0000000..107e605
--- /dev/null
+++ b/test/nw/.gitignore
@@ -0,0 +1,3 @@
+node-webkit.app
+node-webkit-v0.8.4-osx-ia32.zip
+node_modules
\ No newline at end of file
diff --git a/test/nw/Makefile b/test/nw/Makefile
new file mode 100755
index 0000000..9c82233
--- /dev/null
+++ b/test/nw/Makefile
@@ -0,0 +1,39 @@
+NODE_WEBKIT_VERSION=0.8.4
+
+all: app.nw
+
+node_modules/sqlite3:
+	npm install https://github.com/mapbox/node-sqlite3/tarball/master --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION)
+
+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
+
+./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
+	zip app.nw index.html package.json node_modules
+
+test: ./node-webkit.app app.nw
+	./node-webkit.app/Contents/MacOS/node-webkit app.nw
+
+package: ./node-webkit.app Makefile package.json index.html node_modules/sqlite3
+	rm -rf node-sqlite-test.app
+	cp -r ./node-webkit.app node-sqlite-test.app
+	mkdir ./node-sqlite-test.app/Contents/Resources/app.nw/
+	cp package.json ./node-sqlite-test.app/Contents/Resources/app.nw/
+	cp index.html ./node-sqlite-test.app/Contents/Resources/app.nw/
+	cp -r node_modules/ ./node-sqlite-test.app/Contents/Resources/app.nw/
+	./node-sqlite-test.app/Contents/MacOS/node-webkit
+
+clean:
+	rm -rf ./node_modules/sqlite3
+	rm -f ./app.nw
+	rm -rf node-sqlite-test.app
+	rm -f credits.html
+	rm -f nwsnapshot
+
+.PHONY: test
diff --git a/test/nw/index.html b/test/nw/index.html
new file mode 100644
index 0000000..9a1bb90
--- /dev/null
+++ b/test/nw/index.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Hello World!</title>
+  </head>
+  <body>
+    <h1>Hello World!</h1>
+    Using node-sqlite3:
+    <script>
+    var sqlite = require('sqlite3');
+    document.write(sqlite.VERSION);
+    </script>.
+  </body>
+</html>
\ No newline at end of file
diff --git a/test/nw/package.json b/test/nw/package.json
new file mode 100644
index 0000000..d1b4aee
--- /dev/null
+++ b/test/nw/package.json
@@ -0,0 +1,9 @@
+{
+  "name": "nw-demo",
+  "main": "index.html",
+  "window": {
+    "toolbar": false,
+    "width": 800,
+    "height": 600
+  }
+}
\ No newline at end of file
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