diff --git a/.gitignore b/.gitignore index b62f417f0..1197bbe86 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,9 @@ -.lock-wscript *.dylib *.so *.o *.lo *.Makefile *.target.gyp.mk -stage lib/binding build out @@ -18,6 +16,7 @@ gyp-mac-tool .dirstamp npm-debug.log test/support/big.db -lib/node_sqlite3.node test/tmp -.DS_Store \ No newline at end of file +test/nw/app.nw +.DS_Store +.idea diff --git a/.npmignore b/.npmignore new file mode 100644 index 000000000..733dbe72a --- /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 92ac5dd3c..9fcfef162 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,67 +1,53 @@ language: cpp +# http://docs.travis-ci.com/user/multi-os/ +os: + - linux + - osx + +# 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]/ + env: matrix: - - export NODE_VERSION="0.8" - - export NODE_VERSION="0.10" + - NODE_VERSION="0.10.40" # ABI 11 + - NODE_VERSION="0.12.7" # ABI 14 + - NODE_VERSION="iojs-1.8.4" # ABI 43 + - NODE_VERSION="iojs-2.3.4" # ABI 44 + - NODE_WEBKIT="0.8.6" TARGET_ARCH="ia32" + - NODE_WEBKIT="0.8.6" TARGET_ARCH="x64" + - NODE_WEBKIT="0.10.5" TARGET_ARCH="ia32" + - NODE_WEBKIT="0.10.5" TARGET_ARCH="x64" global: - - secure: QhuP5E/kYL1j1KDkHGJtk6DSJr1RH4DR/JrC62Viuf5Du8jE+i0kPWfF2MxtuEmKo35orhpu8t8mzKygWfuO63WPuuIE9qd/+V/y99Lqcj0tEN6wJ5RnywktbTJWg23zphjhmYq3Xj8DLVEikCZBwHtlbygkO9Q60cn1PK+bnPg= - - secure: HxCS2dQAWI0KmCFnFNNZoucG4FeAW+itG7+Hp0dNtwmxZzGOZYFO2bZcGvTAMNfVN++oqLxTebYQI1oB5yUl5mPJjrjthaGS6Zq3S6rfJcXiv+icYgEXlR6ejQ97dsHw1Jeg8nedCQlI4kHfvG6pgBLhq9hnugxH1Cjhdt14E9U= + - secure: PifMOSnn+mWR1RUptXse+fLvWiTrzg0R/mazO7RWhXHWBKv0uAJ/qV3dI0GIRBLtjG10Iy+tT5RNh1TIbBzB9Y67wMcGvylUPG1+3EOKoBMEPnOD9AgCEQw4SOXfGPx0cq2N6ueSKieCgu1yKN9Wq7XCbE+zTk/DiRNIdLirVoo= + - secure: cc4esJY1vPXL31IeumAJoKWDDO2BTGFiltwfO1jbTbiV7QT911QUjTUasxXIVpOaHNCpxSTyevPwwTWfzt2EtF92Lli+qhQ2bbzMiDSBZstSrHdAe62Ai2M1oYYUwk/0cABB/2nO9uRyYwITCxpTSNzZBrYhn3C29WqBhPeVDmM= + +matrix: + exclude: + - env: NODE_WEBKIT="0.8.6" TARGET_ARCH="x64" + os: osx before_install: -# put node-pre-gyp on path -- export PATH=./node_modules/.bin/:$PATH +# check if tag exists and matches package.json +- scripts/validate_tag.sh - echo $NODE_VERSION -- git clone https://github.com/creationix/nvm.git ../.nvm -- source ../.nvm/nvm.sh -- nvm install $NODE_VERSION -- nvm use $NODE_VERSION +# upgrade nvm - node --version - npm --version -- npm install mocha -- platform=$(uname -s | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/") +- npm update -g npm +- npm --version install: -# test installing from source -- npm install --build-from-source -- npm test +# put node-pre-gyp on path +- export PATH=./node_modules/.bin/:$PATH before_script: -# test publishing -- echo $TRAVIS_BRANCH -- echo $TRAVIS_COMMIT -- echo `git describe --tags --always HEAD` -- PUBLISH=false -- if [ "[publish]" = `git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n'` ]; then echo yes;PUBLISH=true; fi; -- if [[ `git describe --contains $( git rev-parse HEAD )` ]]; then echo yes;PUBLISH=true; fi; -- if [[ $PUBLISH == true ]]; then node-pre-gyp package publish; fi +# get commit message +- export COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n') script: -# test install from published binary -- make clean -- npm install -- npm test -- make clean -# test source compile against system libsqlite3 -- if [[ "$platform" == 'linux' ]]; then sudo apt-get -qq update; sudo apt-get -qq install libsqlite3-dev; fi -- make clean -- npm install --build-from-source --sqlite=/usr -- npm test -- make clean -# node v0.8 and above provide pre-built 32 bit and 64 bit binaries -# so here we use the 32 bit ones to also test 32 bit builds -- NVER=`node -v` -- wget http://nodejs.org/dist/${NVER}/node-${NVER}-${platform}-x86.tar.gz -- tar xf node-${NVER}-${platform}-x86.tar.gz -# enable 32 bit node -- export PATH=$(pwd)/node-${NVER}-${platform}-x86/bin:$PATH -# install 32 bit compiler toolchain -- if [[ "$platform" == 'linux' ]]; then sudo apt-get -y install gcc-multilib g++-multilib; fi -# test source compile in 32 bit mode with internal libsqlite3 -- if [[ "$platform" == 'linux' ]]; then CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source; else npm install --build-from-source; fi -- npm test -# publish 32 bit build -- if [[ $PUBLISH == true ]]; then node-pre-gyp package publish; fi; -- make clean -# test source compile in 32 bit mode against external libsqlite3 -- if [[ "$platform" == 'linux' ]]; then sudo apt-get -y install libsqlite3-dev:i386; CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source --sqlite=/usr; npm test; fi +- if [[ "${NODE_VERSION}" ]]; then ./scripts/build_against_node.sh; fi; +- if [[ "${NODE_WEBKIT}" ]]; then ./scripts/build_against_node_webkit.sh; fi; diff --git a/CHANGELOG.md b/CHANGELOG.md index a255bf83a..83f68e5ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,110 @@ -# Changlog +# Changelog + +## 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@0.6.8 + +## 3.0.8 + + - Fixed build regression against FreeBSD + - Upgraded node-pre-gyp@0.6.7 + +## 3.0.7 + + - Fixed build regression against ARM and i386 linux + - Upgraded node-pre-gyp@0.6.6 + - Added support for io.js 2.0.0 + +## 3.0.6 + + - Upgraded node-pre-gyp@0.6.5 + - Upgraded nan@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@0.6.1 + +## 3.0.3 + + - Upgraded to node-pre-gyp@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@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@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@0.5.x from node-pre-gyp@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 @@ -36,5 +142,3 @@ Released October 22nd, 2013 Released August 7th, 2013 - Minor readme additions and code optimizations - - diff --git a/Makefile b/Makefile index c986b98ec..56fcb276a 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,46 @@ -build: +#http://www.gnu.org/prep/standards/html_node/Standard-Targets.html#Standard-Targets + +all: build + +./node_modules: npm install --build-from-source +build: ./node_modules + ./node_modules/.bin/node-pre-gyp build --loglevel=silent + +debug: + ./node_modules/.bin/node-pre-gyp rebuild --debug + +verbose: + ./node_modules/.bin/node-pre-gyp rebuild --loglevel=verbose + clean: - rm -f ./lib/node_sqlite3.node - rm -rf ./lib/binding/ - #rm -f ./test/support/big.db* - rm -f ./test/tmp/* - rm -rf ./deps/sqlite-autoconf-*/ - rm -rf ./build - rm -rf ./out + @rm -rf ./build + rm -rf lib/binding/ + rm -f test/support/big.db-journal + rm -rf ./node_modules/ +grind: + valgrind --leak-check=full node node_modules/.bin/_mocha + +testpack: + rm -f ./*tgz + npm pack + tar -ztvf *tgz + rm -f ./*tgz + +rebuild: + @make clean + @make + +ifndef only test: - npm test + @PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec +else +test: + @PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec test/${only}.test.js +endif + +check: test -.PHONY: build clean test +.PHONY: test clean build diff --git a/README.md b/README.md index a9de89e06..4275c4561 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,23 @@ -# 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) +[![Dependencies](https://david-dm.org/mapbox/node-sqlite3.svg)](https://david-dm.org/mapbox/node-sqlite3) -[![Build Status](https://travis-ci.org/mapbox/node-sqlite3.png?branch=master)](https://travis-ci.org/mapbox/node-sqlite3) -[![npm package version](https://badge.fury.io/js/sqlite3.png)](https://npmjs.org/package/sqlite3) +## Supported platforms -# USAGE +The `sqlite3` module works with Node.js v0.10.x or v0.12.x and io.js v1.x or 2.x. + +Binaries for most Node versions and platforms are provided by default via [node-pre-gyp](https://github.com/mapbox/node-pre-gyp). + +The `sqlite3` module also works with [node-webkit](https://github.com/rogerwang/node-webkit) if node-webkit contains a supported version of Node.js engine. [(See below.)](#building-for-node-webkit) + +SQLite's [SQLCipher extension](https://github.com/sqlcipher/sqlcipher) is also supported. [(See below.)](#building-for-sqlcipher) + +# Usage **Note:** the module must be [installed](#installing) before use. @@ -33,18 +42,15 @@ db.serialize(function() { db.close(); ``` +# Features - -# FEATURES - -* Straightforward query and parameter binding interface -* Full Buffer/Blob support -* Extensive [debugging support](https://github.com/mapbox/node-sqlite3/wiki/Debugging) -* [Query serialization](https://github.com/mapbox/node-sqlite3/wiki/Control-Flow) API -* [Extension support](https://github.com/mapbox/node-sqlite3/wiki/Extensions) -* Big test suite -* Written in modern C++ and tested for memory leaks - + - Straightforward query and parameter binding interface + - Full Buffer/Blob support + - Extensive [debugging support](https://github.com/mapbox/node-sqlite3/wiki/Debugging) + - [Query serialization](https://github.com/mapbox/node-sqlite3/wiki/Control-Flow) API + - [Extension support](https://github.com/mapbox/node-sqlite3/wiki/Extensions) + - Big test suite + - Written in modern C++ and tested for memory leaks # API @@ -52,7 +58,7 @@ db.close(); See the [API documentation](https://github.com/mapbox/node-sqlite3/wiki) in the wiki. -# INSTALLING +# Installing You can use [`npm`](https://github.com/isaacs/npm) to download and install: @@ -65,36 +71,9 @@ and thus your system must meet [node-gyp's requirements](https://github.com/T 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). - - -# REBUILDING FOR NODE-WEBKIT - -Because of ABI differences, only a rebuilt version of `sqlite3` can be used in [node-webkit](https://github.com/rogerwang/node-webkit). - -After the `sqlite3` module is installed (according to the previous section), do the following: - -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: +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. -``` -NODE_WEBKIT_VERSION="0.8.4" # see latest version at https://github.com/rogerwang/node-webkit#downloads -nw-gyp rebuild --target=${NODE_WEBKIT_VERSION} -``` - -Remember the following: - -* In the `nw-gyp rebuild` command, specify the actual target version of your node-webkit. The command must be run in sqlite3's directory (where its `package.json` resides). - -* 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. - -Visit the “[Using Node modules](https://github.com/rogerwang/node-webkit/wiki/Using-Node-modules)” article in the node-webkit's wiki for more details. - - -# BUILDING FROM THE SOURCE +## Source install Unless building via `npm install` (which uses its own `node-gyp`) you will need `node-gyp` installed globally: @@ -123,8 +102,74 @@ Note, if building against homebrew-installed sqlite on OS X you can do: ./configure --sqlite=/usr/local/opt/sqlite/ make +## 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. Build the module with the custom flags of `--runtime`, `--target_arch`, and `--target`: + +```sh +NODE_WEBKIT_VERSION="0.8.6" # see latest version at https://github.com/rogerwang/node-webkit#downloads +npm install sqlite3 --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION) +``` + +This command internally calls out to [`node-pre-gyp`](https://github.com/mapbox/node-pre-gyp) which itself calls out to [`nw-gyp`](https://github.com/rogerwang/nw-gyp) when the `--runtime=node-webkit` option is passed. + +You can also run this command from within a `node-sqlite3` checkout: + +```sh +npm install --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION) +``` + +Remember the following: + +* You must provide the right `--target_arch` flag. `ia32` is needed to target 32bit node-webkit builds, while `x64` will target 64bit node-webkit builds (if available for your platform). + +* After the `sqlite3` package is 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. + +Visit the “[Using Node modules](https://github.com/rogerwang/node-webkit/wiki/Using-Node-modules)” article in the node-webkit's wiki for more details. + +## Building for sqlcipher + +For instructions for building sqlcipher see +[Building SQLCipher for node.js](https://coolaj86.com/articles/building-sqlcipher-for-node-js-on-raspberry-pi-2/) + +To run node-sqlite3 against sqlcipher you need to compile from source by passing build options like: + + npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/ + + node -e 'require("sqlite3")' + +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: + +### On OS X with Homebrew -# TESTING +Set the location where `brew` installed it: + + 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")' + +### On most Linuxes (including Raspberry Pi) + +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 [mocha](https://github.com/visionmedia/mocha) is required to run unit tests. @@ -134,8 +179,7 @@ In sqlite3's directory (where its `package.json` resides) run the following: npm test - -# CONTRIBUTORS +# Contributors * [Konstantin Käfer](https://github.com/kkaefer) * [Dane Springmeyer](https://github.com/springmeyer) @@ -152,8 +196,7 @@ In sqlite3's directory (where its `package.json` resides) run the following: * [Mithgol](https://github.com/Mithgol) - -# ACKNOWLEDGEMENTS +# Acknowledgments Thanks to [Orlando Vazquez](https://github.com/orlandov), [Eric Fredricksen](https://github.com/grumdrig) and @@ -162,6 +205,6 @@ Thanks to [Orlando Vazquez](https://github.com/orlandov), Development of this module is sponsored by [MapBox](http://mapbox.org/). -# LICENSE +# License `node-sqlite3` is [BSD licensed](https://github.com/mapbox/node-sqlite3/raw/master/LICENSE). diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..60afd15bc --- /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: 1.8.1 + platform: x86 + msvs_toolset: 12 + - nodejs_version: 1.8.1 + platform: x64 + msvs_toolset: 12 + - nodejs_version: 2.0.0 + platform: x64 + msvs_toolset: 12 + - nodejs_version: 2.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 6fcc0db40..a0c5faa53 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,8 +2,7 @@ "includes": [ "deps/common-sqlite.gypi" ], "variables": { "sqlite%":"internal", - "module_name":"node_sqlite3", - "module_path":"./lib/" + "sqlite_libname%":"sqlite3" }, "targets": [ { @@ -11,12 +10,19 @@ "include_dirs": ["= v0.10.4 and v0.11.7 - // https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e - this.node_abi = 'node-v' + (+process.versions.modules); - } else { - this.node_abi = 'v8-' + process.versions.v8.split('.').slice(0,2).join('.'); - } -} - -Binary.prototype.filename = function() { - return this.name + '.node'; -} - -Binary.prototype.compression = function() { - return '.tar.gz'; -} - -Binary.prototype.getBasePath = function() { - return this.node_abi - + '-' + this.platform - + '-' + this.target_arch; -} - -Binary.prototype.getRequirePath = function(configuration) { - return './' + path.join('binding', - configuration || this.configuration, - this.getBasePath(), - this.filename()); -} - -Binary.prototype.getModuleAbi = function() { - return this.name + '-v' + this.module_maj_min + '.' + this.module_abi; -} - -Binary.prototype.getArchivePath = function() { - return this.getModuleAbi() - + '-' - + this.getBasePath() - + this.compression(); -} - -Binary.prototype.getRemotePath = function() { - return this.uri+this.configuration+'/'+this.getArchivePath(); -} - -module.exports.Binary = Binary; \ No newline at end of file diff --git a/lib/sqlite3.js b/lib/sqlite3.js index f0d35a4ef..466b90230 100644 --- a/lib/sqlite3.js +++ b/lib/sqlite3.js @@ -1,13 +1,24 @@ -var binding = require('./node_sqlite3.node'); -var sqlite3 = module.exports = exports = binding; +var binary = require('node-pre-gyp'); var path = require('path'); -var util = require('util'); +var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json'))); +var binding = require(binding_path); +var sqlite3 = module.exports = exports = binding; var EventEmitter = require('events').EventEmitter; -function errorCallback(args) { - if (typeof args[args.length - 1] === 'function') { - var callback = args[args.length - 1]; - return function(err) { if (err) callback(err); }; +function normalizeMethod (fn) { + return function (sql) { + var errBack; + var args = Array.prototype.slice.call(arguments, 1); + if (typeof args[args.length - 1] === 'function') { + var callback = args[args.length - 1]; + errBack = function(err) { + if (err) { + callback(err); + } + }; + } + var statement = new Statement(this, sql, errBack); + return fn.call(this, statement, args); } } @@ -23,9 +34,7 @@ sqlite3.cached = { return new Database(file, a, b); } - if (file[0] !== '/') { - file = path.join(process.cwd(), file); - } + file = path.resolve(file); if (!sqlite3.cached.objects[file]) { var db =sqlite3.cached.objects[file] = new Database(file, a, b); @@ -54,56 +63,40 @@ inherits(Database, EventEmitter); inherits(Statement, EventEmitter); // Database#prepare(sql, [bind1, bind2, ...], [callback]) -Database.prototype.prepare = function(sql) { - var params = Array.prototype.slice.call(arguments, 1); - - if (!params.length || (params.length === 1 && typeof params[0] === 'function')) { - return new Statement(this, sql, params[0]); - } - else { - var statement = new Statement(this, sql, errorCallback(params)); - return statement.bind.apply(statement, params); - } -}; +Database.prototype.prepare = normalizeMethod(function(statement, params) { + return params.length + ? statement.bind.apply(statement, params) + : statement; +}); // Database#run(sql, [bind1, bind2, ...], [callback]) -Database.prototype.run = function(sql) { - var params = Array.prototype.slice.call(arguments, 1); - var statement = new Statement(this, sql, errorCallback(params)); +Database.prototype.run = normalizeMethod(function(statement, params) { statement.run.apply(statement, params).finalize(); return this; -}; +}); // Database#get(sql, [bind1, bind2, ...], [callback]) -Database.prototype.get = function(sql) { - var params = Array.prototype.slice.call(arguments, 1); - var statement = new Statement(this, sql, errorCallback(params)); +Database.prototype.get = normalizeMethod(function(statement, params) { statement.get.apply(statement, params).finalize(); return this; -}; +}); // Database#all(sql, [bind1, bind2, ...], [callback]) -Database.prototype.all = function(sql) { - var params = Array.prototype.slice.call(arguments, 1); - var statement = new Statement(this, sql, errorCallback(params)); +Database.prototype.all = normalizeMethod(function(statement, params) { statement.all.apply(statement, params).finalize(); return this; -}; +}); // Database#each(sql, [bind1, bind2, ...], [callback], [complete]) -Database.prototype.each = function(sql) { - var params = Array.prototype.slice.call(arguments, 1); - var statement = new Statement(this, sql, errorCallback(params)); +Database.prototype.each = normalizeMethod(function(statement, params) { statement.each.apply(statement, params).finalize(); return this; -}; +}); -Database.prototype.map = function(sql) { - var params = Array.prototype.slice.call(arguments, 1); - var statement = new Statement(this, sql, errorCallback(params)); +Database.prototype.map = normalizeMethod(function(statement, params) { statement.map.apply(statement, params).finalize(); return this; -}; +}); Statement.prototype.map = function() { var params = Array.prototype.slice.call(arguments); @@ -163,22 +156,30 @@ Database.prototype.removeAllListeners = function(type) { sqlite3.verbose = function() { if (!isVerbose) { var trace = require('./trace'); - trace.extendTrace(Database.prototype, 'prepare'); - trace.extendTrace(Database.prototype, 'get'); - trace.extendTrace(Database.prototype, 'run'); - trace.extendTrace(Database.prototype, 'all'); - trace.extendTrace(Database.prototype, 'each'); - trace.extendTrace(Database.prototype, 'map'); - trace.extendTrace(Database.prototype, 'exec'); - trace.extendTrace(Database.prototype, 'close'); - trace.extendTrace(Statement.prototype, 'bind'); - trace.extendTrace(Statement.prototype, 'get'); - trace.extendTrace(Statement.prototype, 'run'); - trace.extendTrace(Statement.prototype, 'all'); - trace.extendTrace(Statement.prototype, 'each'); - trace.extendTrace(Statement.prototype, 'map'); - trace.extendTrace(Statement.prototype, 'reset'); - trace.extendTrace(Statement.prototype, 'finalize'); + [ + 'prepare', + 'get', + 'run', + 'all', + 'each', + 'map', + 'close', + 'exec' + ].forEach(function (name) { + trace.extendTrace(Database.prototype, name); + }); + [ + 'bind', + 'get', + 'run', + 'all', + 'each', + 'map', + 'reset', + 'finalize', + ].forEach(function (name) { + trace.extendTrace(Statement.prototype, name); + }); isVerbose = true; } diff --git a/package.json b/package.json index 06042e07d..75b727a36 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,18 @@ { "name": "sqlite3", "description": "Asynchronous, non-blocking SQLite3 bindings", - "version": "2.2.0", + "version": "3.0.10", "homepage": "http://github.com/mapbox/node-sqlite3", "author": { "name": "MapBox", "url": "https://mapbox.com/" }, "binary": { - "module_name": "node_sqlite3", - "module_path": "./lib", - "remote_uri": "http://node-sqlite3.s3.amazonaws.com", - "template": "{configuration}/{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz" + "module_name" : "node_sqlite3", + "module_path" : "./lib/binding/{node_abi}-{platform}-{arch}", + "host" : "https://mapbox-node-binary.s3.amazonaws.com", + "remote_path" : "./{name}/v{version}/{toolset}/", + "package_name": "{node_abi}-{platform}-{arch}.tar.gz" }, "contributors": [ "Konstantin Käfer ", @@ -28,31 +29,40 @@ "Johannes Schauer ", "Nathan Rajlich ", "AJ ONeal ", - "Mithgol" + "Mithgol", + "Ben Noordhuis " ], "repository": { "type": "git", "url": "git://github.com/mapbox/node-sqlite3.git" }, "dependencies": { - "node-pre-gyp": "~0.2.5", - "nan": "~0.8.0" + "nan": "~1.8.4", + "node-pre-gyp": "~0.6.9" }, "bundledDependencies": [ "node-pre-gyp" ], - "engines": { - "node": ">= 0.8.0 < 0.11.0" + "devDependencies": { + "mocha": "1.x", + "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 -s 20000" + "test": "mocha -R spec --timeout 480000" }, "licenses": [ { "type": "BSD" } ], + "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 000000000..d5f8536e8 --- /dev/null +++ b/scripts/build-appveyor.bat @@ -0,0 +1,153 @@ +@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^: && cl +IF %ERRORLEVEL% NEQ 0 GOTO ERROR + +ECHO using MSBuild^: && 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" powershell Install-Product node $env:nodejs_version $env:Platform +IF %ERRORLEVEL% NEQ 0 GOTO ERROR + +IF /I "%msvs_toolset%"=="12" GOTO NODE_INSTALLED + + +::custom node for VS2015 +SET ARCHPATH= +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^: +where node +ECHO available npm^: +where npm + +ECHO node^: && node -v +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 000000000..6c7e26932 --- /dev/null +++ b/scripts/build-local.bat @@ -0,0 +1,59 @@ +@ECHO OFF +SETLOCAL +SET EL=0 + +ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +SET PATH=C:\Python27;%PATH% + +SET APPVEYOR_REPO_COMMIT_MESSAGE=local build + +IF EXIST lib\binding ECHO deleting lib/binding && RD /Q /S lib\binding +IF %ERRORLEVEL% NEQ 0 GOTO ERROR +IF EXIST node_modules ECHO deleting node_modules && RD /Q /S node_modules +IF %ERRORLEVEL% NEQ 0 GOTO ERROR + +ECHO ============================ +ECHO VS2013 +ECHO ============================ +SET nodejs_version=0.10.36 +SET platform=x64 +SET msvs_toolset=12 +SET TOOLSET_ARGS= + +CALL scripts\build-appveyor.bat +IF %ERRORLEVEL% NEQ 0 GOTO ERROR + + + + +IF EXIST lib\binding ECHO deleting lib/binding && RD /Q /S lib\binding +IF %ERRORLEVEL% NEQ 0 GOTO ERROR +IF EXIST node_modules ECHO deleting node_modules && RD /Q /S node_modules +IF %ERRORLEVEL% NEQ 0 GOTO ERROR + +ECHO ============================ +ECHO VS2015 +ECHO ============================ +SET nodejs_version=0.12.7 +SET platform=x86 +SET msvs_toolset=14 +SET TOOLSET_ARGS=--dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140 + +CALL scripts\build-appveyor.bat +IF %ERRORLEVEL% NEQ 0 GOTO ERROR + + + + +GOTO DONE + +:ERROR +ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +ECHO ERRORLEVEL^: %ERRORLEVEL% +SET EL=%ERRORLEVEL% + +:DONE +ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +EXIT /b %EL% diff --git a/scripts/build.bat b/scripts/build.bat deleted file mode 100644 index 9263a2771..000000000 --- a/scripts/build.bat +++ /dev/null @@ -1,49 +0,0 @@ -@rem setup -@rem git clone git://github.com/marcelklehr/nodist.git -@rem create ~/.node_pre_gyprc -@rem note, for 64 builds you may need to win7 sdk terminal -@rem https://github.com/TooTallNate/node-gyp/issues/112 -set PATH=c:\dev2\nodist\bin;%PATH% -set PATH=node_modules\.bin;%PATH% -set PATH=%PATH%;c:\Python27 - -@rem 32 bit -set NODIST_X64=0 -nodist use stable -node -e "console.log(process.version + ' ' + process.arch)" -node-pre-gyp clean -npm install --build-from-source -npm test -node-pre-gyp package publish -node-pre-gyp clean - -@rem 64 bit -@ rem cannot open input file 'kernel32.lib' http://www.microsoft.com/en-us/download/details.aspx?id=4422 -set NODIST_X64=1 -nodist use stable -node -e "console.log(process.version + ' ' + process.arch)" -node-pre-gyp clean -npm install --build-from-source -npm test -node-pre-gyp package publish -node-pre-gyp clean - -@ rem 32 bit v0.8x -set NODIST_X64=0 -nodist use v0.8 -node -e "console.log(process.version + ' ' + process.arch)" -node-pre-gyp clean -npm install --build-from-source -npm test -node-pre-gyp package publish -node-pre-gyp clean - -@rem 64 bit v0.8.x -set NODIST_X64=1 -nodist use v0.8 -node -e "console.log(process.version + ' ' + process.arch)" -node-pre-gyp clean -npm install --build-from-source -npm test -node-pre-gyp package publish -node-pre-gyp clean diff --git a/scripts/build_against_node.sh b/scripts/build_against_node.sh new file mode 100755 index 000000000..fdb0a6488 --- /dev/null +++ b/scripts/build_against_node.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash + +if [[ ! -d ../.nvm ]]; then + git clone https://github.com/creationix/nvm.git ../.nvm +fi +source ../.nvm/nvm.sh +nvm install $NODE_VERSION +nvm use $NODE_VERSION + +set -u -e + +function publish() { + if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then + node-pre-gyp publish + node-pre-gyp info + node-pre-gyp clean + make clean + # now install from binary + INSTALL_RESULT=$(npm install --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;false; fi + # If success then we arrive here so lets clean up + node-pre-gyp clean + fi +} + +# test installing from source +npm install --build-from-source +node-pre-gyp package testpackage +npm test + +publish + +# now test building against shared sqlite +if [[ $(uname -s) == 'Darwin' ]]; then + brew install sqlite + npm install --build-from-source --sqlite=$(brew --prefix) +else + sudo apt-get -qq update + sudo apt-get -qq install libsqlite3-dev + npm install --build-from-source --sqlite=/usr +fi +npm test + +platform=$(uname -s | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/") + +if [[ $(uname -s) == 'Linux' ]]; then + sudo apt-get -y install gcc-multilib g++-multilib + # 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 + 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 + 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 + sudo apt-get -y install libsqlite3-dev:i386 + CC=gcc-4.6 CXX=g++-4.6 npm install --build-from-source --sqlite=/usr + npm test + fi +fi diff --git a/scripts/build_against_node_webkit.sh b/scripts/build_against_node_webkit.sh new file mode 100755 index 000000000..94706b4fd --- /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 000000000..2a0878fc4 --- /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/validate_tag.sh b/scripts/validate_tag.sh new file mode 100755 index 000000000..67d039b70 --- /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 37b42482e..2b167cec2 100644 --- a/src/async.h +++ b/src/async.h @@ -26,7 +26,7 @@ template class Async { : 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(listener)); } static void listener(uv_async_t* handle, int status) { diff --git a/src/database.cc b/src/database.cc index b2df6dbe4..d34b865a8 100644 --- a/src/database.cc +++ b/src/database.cc @@ -12,10 +12,10 @@ Persistent Database::constructor_template; void Database::Init(Handle target) { NanScope(); - Local t = FunctionTemplate::New(New); + Local t = NanNew(New); t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(String::NewSymbol("Database")); + t->SetClassName(NanNew("Database")); NODE_SET_PROTOTYPE_METHOD(t, "close", Close); NODE_SET_PROTOTYPE_METHOD(t, "exec", Exec); @@ -27,22 +27,24 @@ void Database::Init(Handle target) { NODE_SET_GETTER(t, "open", OpenGetter); - NanAssignPersistent(FunctionTemplate, constructor_template, t); + NanAssignPersistent(constructor_template, t); - target->Set(String::NewSymbol("Database"), + target->Set(NanNew("Database"), t->GetFunction()); } void Database::Process() { + NanScope(); + if (!open && locked && !queue.empty()) { - EXCEPTION(String::New("Database handle is closed"), SQLITE_MISUSE, exception); + EXCEPTION(NanNew("Database handle is closed"), SQLITE_MISUSE, exception); Local argv[] = { exception }; bool called = false; // Call all callbacks with the error object. while (!queue.empty()) { Call* call = queue.front(); - Local cb = NanPersistentToLocal(call->baton->callback); + Local cb = NanNew(call->baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { TRY_CATCH_CALL(NanObjectWrapHandle(this), cb, 1, argv); called = true; @@ -57,7 +59,7 @@ void Database::Process() { // When we couldn't call a callback function, emit an error on the // Database object. if (!called) { - Local args[] = { String::NewSymbol("error"), exception }; + Local args[] = { NanNew("error"), exception }; EMIT_EVENT(NanObjectWrapHandle(this), 2, args); } return; @@ -80,15 +82,16 @@ void Database::Process() { } void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { + NanScope(); if (!open && locked) { - EXCEPTION(String::New("Database is closed"), SQLITE_MISUSE, exception); - Local cb = NanPersistentToLocal(baton->callback); + EXCEPTION(NanNew("Database is closed"), SQLITE_MISUSE, exception); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { exception }; TRY_CATCH_CALL(NanObjectWrapHandle(this), cb, 1, argv); } else { - Local argv[] = { String::NewSymbol("error"), exception }; + Local argv[] = { NanNew("error"), exception }; EMIT_EVENT(NanObjectWrapHandle(this), 2, argv); } return; @@ -128,8 +131,8 @@ NAN_METHOD(Database::New) { Database* db = new Database(); db->Wrap(args.This()); - args.This()->Set(String::NewSymbol("filename"), args[0]->ToString(), ReadOnly); - args.This()->Set(String::NewSymbol("mode"), Integer::New(mode), ReadOnly); + args.This()->ForceSet(NanNew("filename"), args[0]->ToString(), ReadOnly); + args.This()->ForceSet(NanNew("mode"), NanNew(mode), ReadOnly); // Start opening the database. OpenBaton* baton = new OpenBaton(db, callback, *filename, mode); @@ -173,26 +176,26 @@ void Database::Work_AfterOpen(uv_work_t* req) { Local argv[1]; if (baton->status != SQLITE_OK) { - EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); + EXCEPTION(NanNew(baton->message.c_str()), baton->status, exception); argv[0] = exception; } else { db->open = true; - argv[0] = NanNewLocal(Null()); + argv[0] = NanNew(NanNull()); } - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } else if (!db->open) { - Local args[] = { String::NewSymbol("error"), argv[0] }; + Local args[] = { NanNew("error"), argv[0] }; EMIT_EVENT(NanObjectWrapHandle(db), 2, args); } if (db->open) { - Local args[] = { String::NewSymbol("open") }; + Local args[] = { NanNew("open") }; EMIT_EVENT(NanObjectWrapHandle(db), 1, args); db->Process(); } @@ -203,7 +206,7 @@ void Database::Work_AfterOpen(uv_work_t* req) { NAN_GETTER(Database::OpenGetter) { NanScope(); Database* db = ObjectWrap::Unwrap(args.This()); - NanReturnValue(Boolean::New(db->open)); + NanReturnValue(NanNew(db->open)); } NAN_METHOD(Database::Close) { @@ -250,29 +253,29 @@ void Database::Work_AfterClose(uv_work_t* req) { Local argv[1]; if (baton->status != SQLITE_OK) { - EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); + EXCEPTION(NanNew(baton->message.c_str()), 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] = NanNewLocal(Null()); + argv[0] = NanNew(NanNull()); } - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); // Fire callbacks. if (!cb.IsEmpty() && cb->IsFunction()) { TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } else if (db->open) { - Local args[] = { String::NewSymbol("error"), argv[0] }; + Local args[] = { NanNew("error"), argv[0] }; EMIT_EVENT(NanObjectWrapHandle(db), 2, args); } if (!db->open) { - Local args[] = { String::NewSymbol("close"), argv[0] }; + Local args[] = { NanNew("close"), argv[0] }; EMIT_EVENT(NanObjectWrapHandle(db), 1, args); db->Process(); } @@ -322,17 +325,17 @@ NAN_METHOD(Database::Configure) { REQUIRE_ARGUMENTS(2); - if (args[0]->Equals(String::NewSymbol("trace"))) { + if (args[0]->Equals(NanNew("trace"))) { Local handle; Baton* baton = new Baton(db, handle); db->Schedule(RegisterTraceCallback, baton); } - else if (args[0]->Equals(String::NewSymbol("profile"))) { + else if (args[0]->Equals(NanNew("profile"))) { Local handle; Baton* baton = new Baton(db, handle); db->Schedule(RegisterProfileCallback, baton); } - else if (args[0]->Equals(String::NewSymbol("busyTimeout"))) { + else if (args[0]->Equals(NanNew("busyTimeout"))) { if (!args[1]->IsInt32()) { return NanThrowTypeError("Value must be an integer"); } @@ -344,7 +347,7 @@ NAN_METHOD(Database::Configure) { else { return NanThrowError(Exception::Error(String::Concat( args[0]->ToString(), - String::New(" is not a valid configuration option") + NanNew(" is not a valid configuration option") ))); } @@ -393,8 +396,8 @@ void Database::TraceCallback(Database* db, std::string* sql) { // Note: This function is called in the main V8 thread. NanScope(); Local argv[] = { - String::NewSymbol("trace"), - String::New(sql->c_str()) + NanNew("trace"), + NanNew(sql->c_str()) }; EMIT_EVENT(NanObjectWrapHandle(db), 2, argv); delete sql; @@ -432,9 +435,9 @@ void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs) void Database::ProfileCallback(Database *db, ProfileInfo* info) { NanScope(); Local argv[] = { - String::NewSymbol("profile"), - String::New(info->sql.c_str()), - Integer::New((double)info->nsecs / 1000000.0) + NanNew("profile"), + NanNew(info->sql.c_str()), + NanNew((double)info->nsecs / 1000000.0) }; EMIT_EVENT(NanObjectWrapHandle(db), 3, argv); delete info; @@ -476,10 +479,10 @@ void Database::UpdateCallback(Database *db, UpdateInfo* info) { NanScope(); Local argv[] = { - String::NewSymbol(sqlite_authorizer_string(info->type)), - String::New(info->database.c_str()), - String::New(info->table.c_str()), - Integer::New(info->rowid), + NanNew(sqlite_authorizer_string(info->type)), + NanNew(info->database.c_str()), + NanNew(info->table.c_str()), + NanNew(info->rowid), }; EMIT_EVENT(NanObjectWrapHandle(db), 4, argv); delete info; @@ -531,22 +534,22 @@ void Database::Work_AfterExec(uv_work_t* req) { ExecBaton* baton = static_cast(req->data); Database* db = baton->db; - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (baton->status != SQLITE_OK) { - EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); + EXCEPTION(NanNew(baton->message.c_str()), baton->status, exception); if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { exception }; TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } else { - Local args[] = { String::NewSymbol("error"), exception }; + Local args[] = { NanNew("error"), exception }; EMIT_EVENT(NanObjectWrapHandle(db), 2, args); } } else if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { NanNewLocal(Null()) }; + Local argv[] = { NanNew(NanNull()) }; TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } @@ -575,9 +578,9 @@ void Database::Work_Wait(Baton* baton) { assert(baton->db->_handle); assert(baton->db->pending == 0); - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { NanNewLocal(Null()) }; + Local argv[] = { NanNew(NanNull()) }; TRY_CATCH_CALL(NanObjectWrapHandle(baton->db), cb, 1, argv); } @@ -634,22 +637,22 @@ void Database::Work_AfterLoadExtension(uv_work_t* req) { NanScope(); LoadExtensionBaton* baton = static_cast(req->data); Database* db = baton->db; - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (baton->status != SQLITE_OK) { - EXCEPTION(String::New(baton->message.c_str()), baton->status, exception); + EXCEPTION(NanNew(baton->message.c_str()), baton->status, exception); if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { exception }; TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } else { - Local args[] = { String::NewSymbol("error"), exception }; + Local args[] = { NanNew("error"), exception }; EMIT_EVENT(NanObjectWrapHandle(db), 2, args); } } else if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { NanNewLocal(Null()) }; + Local argv[] = { NanNew(NanNull()) }; TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } diff --git a/src/database.h b/src/database.h index eb853bc97..af83ee715 100644 --- a/src/database.h +++ b/src/database.h @@ -1,3 +1,4 @@ + #ifndef NODE_SQLITE3_SRC_DATABASE_H #define NODE_SQLITE3_SRC_DATABASE_H @@ -24,9 +25,10 @@ class Database : public ObjectWrap { static void Init(Handle target); static inline bool HasInstance(Handle val) { + NanScope(); if (!val->IsObject()) return false; Local obj = val->ToObject(); - return NanPersistentToLocal(constructor_template)->HasInstance(obj); + return NanNew(constructor_template)->HasInstance(obj); } struct Baton { @@ -40,11 +42,11 @@ class Database : public ObjectWrap { db(db_), status(SQLITE_OK) { db->Ref(); request.data = this; - NanAssignPersistent(Function, callback, cb_); + NanAssignPersistent(callback, cb_); } virtual ~Baton() { db->Unref(); - callback.Dispose(); + NanDisposePersistent(callback); } }; @@ -108,7 +110,6 @@ class Database : public ObjectWrap { debug_trace(NULL), debug_profile(NULL), update_event(NULL) { - } ~Database() { diff --git a/src/gcc-preinclude.h b/src/gcc-preinclude.h index c515fa631..38c91385c 100644 --- a/src/gcc-preinclude.h +++ b/src/gcc-preinclude.h @@ -1,4 +1,6 @@ // https://rjpower9000.wordpress.com/2012/04/09/fun-with-shared-libraries-version-glibc_2-14-not-found/ +#if defined(__linux__) && defined(__x86_64__) __asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); +#endif diff --git a/src/macros.h b/src/macros.h index 8d2beb3ab..42e57b275 100644 --- a/src/macros.h +++ b/src/macros.h @@ -56,58 +56,54 @@ const char* sqlite_authorizer_string(int type); #define DEFINE_CONSTANT_INTEGER(target, constant, name) \ - (target)->Set( \ - String::NewSymbol(#name), \ - Integer::New(constant), \ + (target)->ForceSet( \ + NanNew(#name), \ + NanNew(constant), \ static_cast(ReadOnly | DontDelete) \ ); #define DEFINE_CONSTANT_STRING(target, constant, name) \ - (target)->Set( \ - String::NewSymbol(#name), \ - String::NewSymbol(constant), \ + (target)->ForceSet( \ + NanNew(#name), \ + NanNew(constant), \ static_cast(ReadOnly | DontDelete) \ ); #define NODE_SET_GETTER(target, name, function) \ (target)->InstanceTemplate() \ - ->SetAccessor(String::NewSymbol(name), (function)); + ->SetAccessor(NanNew(name), (function)); #define GET_STRING(source, name, property) \ - String::Utf8Value name((source)->Get(String::NewSymbol(property))); + String::Utf8Value name((source)->Get(NanNew(property))); #define GET_INTEGER(source, name, property) \ - int name = (source)->Get(String::NewSymbol(property))->Int32Value(); + int name = (source)->Get(NanNew(property))->Int32Value(); #define EXCEPTION(msg, errno, name) \ Local name = Exception::Error( \ String::Concat( \ String::Concat( \ - String::NewSymbol(sqlite_code_string(errno)), \ - String::NewSymbol(": ") \ + NanNew(sqlite_code_string(errno)), \ + NanNew(": ") \ ), \ (msg) \ ) \ ); \ Local name ##_obj = name->ToObject(); \ - name ##_obj->Set(String::NewSymbol("errno"), Integer::New(errno)); \ - name ##_obj->Set(String::NewSymbol("code"), \ - String::NewSymbol(sqlite_code_string(errno))); + name ##_obj->Set(NanNew("errno"), NanNew(errno)); \ + name ##_obj->Set(NanNew("code"), \ + NanNew(sqlite_code_string(errno))); #define EMIT_EVENT(obj, argc, argv) \ TRY_CATCH_CALL((obj), \ - Local::Cast((obj)->Get(String::NewSymbol("emit"))), \ + Local::Cast((obj)->Get(NanNew("emit"))), \ argc, argv \ ); #define TRY_CATCH_CALL(context, callback, argc, argv) \ -{ TryCatch try_catch; \ - MakeCallback((context), (callback), (argc), (argv)); \ - if (try_catch.HasCaught()) { \ - FatalException(try_catch); \ - } } + NanMakeCallback((context), (callback), (argc), (argv)) #define WORK_DEFINITION(name) \ static NAN_METHOD(name); \ diff --git a/src/node_sqlite3.cc b/src/node_sqlite3.cc index 0a78ab22d..42fbabba6 100644 --- a/src/node_sqlite3.cc +++ b/src/node_sqlite3.cc @@ -16,6 +16,7 @@ using namespace node_sqlite3; namespace { void RegisterModule(v8::Handle target) { + NanScope(); Database::Init(target); Statement::Init(target); diff --git a/src/statement.cc b/src/statement.cc index c5dbafcba..37f36d300 100644 --- a/src/statement.cc +++ b/src/statement.cc @@ -14,10 +14,10 @@ Persistent Statement::constructor_template; void Statement::Init(Handle target) { NanScope(); - Local t = FunctionTemplate::New(New); + Local t = NanNew(New); t->InstanceTemplate()->SetInternalFieldCount(1); - t->SetClassName(String::NewSymbol("Statement")); + t->SetClassName(NanNew("Statement")); NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind); NODE_SET_PROTOTYPE_METHOD(t, "get", Get); @@ -27,8 +27,8 @@ void Statement::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "reset", Reset); NODE_SET_PROTOTYPE_METHOD(t, "finalize", Finalize); - NanAssignPersistent(FunctionTemplate, constructor_template, t); - target->Set(String::NewSymbol("Statement"), + NanAssignPersistent(constructor_template, t); + target->Set(NanNew("Statement"), t->GetFunction()); } @@ -60,19 +60,21 @@ void Statement::Schedule(Work_Callback callback, Baton* baton) { } template void Statement::Error(T* baton) { + NanScope(); + Statement* stmt = baton->stmt; // Fail hard on logic errors. assert(stmt->status != 0); - EXCEPTION(String::New(stmt->message.c_str()), stmt->status, exception); + EXCEPTION(NanNew(stmt->message.c_str()), stmt->status, exception); - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { exception }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } else { - Local argv[] = { String::NewSymbol("error"), exception }; + Local argv[] = { NanNew("error"), exception }; EMIT_EVENT(NanObjectWrapHandle(stmt), 2, argv); } } @@ -100,7 +102,7 @@ NAN_METHOD(Statement::New) { Database* db = ObjectWrap::Unwrap(args[0]->ToObject()); Local sql = Local::Cast(args[1]); - args.This()->Set(String::NewSymbol("sql"), sql, ReadOnly); + args.This()->ForceSet(NanNew("sql"), sql, ReadOnly); Statement* stmt = new Statement(db); stmt->Wrap(args.This()); @@ -154,9 +156,9 @@ void Statement::Work_AfterPrepare(uv_work_t* req) { } else { stmt->prepared = true; - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { NanNewLocal(Null()) }; + Local argv[] = { NanNew(NanNull()) }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } } @@ -195,6 +197,8 @@ template Values::Field* } template T* Statement::Bind(_NAN_METHOD_ARGS, int start, int last) { + NanScope(); + if (last < 0) last = args.Length(); Local callback; if (last > start && args[last - 1]->IsFunction()) { @@ -291,11 +295,11 @@ bool Statement::Bind(const Parameters & parameters) { 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; + } } } @@ -338,9 +342,9 @@ void Statement::Work_AfterBind(uv_work_t* req) { } else { // Fire callbacks. - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { NanNewLocal(Null()) }; + Local argv[] = { NanNew(NanNull()) }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } } @@ -401,15 +405,15 @@ void Statement::Work_AfterGet(uv_work_t* req) { } else { // Fire callbacks. - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { if (stmt->status == SQLITE_ROW) { // Create the result array from the data we acquired. - Local argv[] = { NanNewLocal(Null()), RowToJS(&baton->row) }; + Local argv[] = { NanNew(NanNull()), RowToJS(&baton->row) }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv); } else { - Local argv[] = { NanNewLocal(Null()) }; + Local argv[] = { NanNew(NanNull()) }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } } @@ -471,12 +475,12 @@ void Statement::Work_AfterRun(uv_work_t* req) { } else { // Fire callbacks. - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { - NanObjectWrapHandle(stmt)->Set(String::NewSymbol("lastID"), Local(Integer::New(baton->inserted_id))); - NanObjectWrapHandle(stmt)->Set(String::NewSymbol("changes"), Local(Integer::New(baton->changes))); + NanObjectWrapHandle(stmt)->Set(NanNew("lastID"), NanNew(baton->inserted_id)); + NanObjectWrapHandle(stmt)->Set(NanNew("changes"), NanNew(baton->changes)); - Local argv[] = { NanNewLocal(Null()) }; + Local argv[] = { NanNew(NanNull()) }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } } @@ -537,11 +541,11 @@ void Statement::Work_AfterAll(uv_work_t* req) { } else { // Fire callbacks. - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { if (baton->rows.size()) { // Create the result array from the data we acquired. - Local result(Array::New(baton->rows.size())); + Local result(NanNew(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++) { @@ -549,14 +553,14 @@ void Statement::Work_AfterAll(uv_work_t* req) { delete *it; } - Local argv[] = { NanNewLocal(Null()), result }; + Local argv[] = { NanNew(NanNull()), result }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv); } else { // There were no result rows. Local argv[] = { - NanNewLocal(Null()), - NanNewLocal(Array::New(0)) + NanNew(NanNull()), + NanNew(0) }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv); } @@ -582,7 +586,7 @@ NAN_METHOD(Statement::Each) { return NanThrowError("Data type is not supported"); } else { - NanAssignPersistent(Function, baton->completed, completed); + NanAssignPersistent(baton->completed, completed); stmt->Schedule(Work_BeginEach, baton); NanReturnValue(args.This()); } @@ -592,9 +596,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(baton); - each_baton->async = new Async(each_baton->stmt, AsyncEach); - NanAssignPersistent(Function, each_baton->async->item_cb, each_baton->callback); - NanAssignPersistent(Function, each_baton->async->completed_cb, each_baton->completed); + each_baton->async = new Async(each_baton->stmt, reinterpret_cast(AsyncEach)); + NanAssignPersistent(each_baton->async->item_cb, each_baton->callback); + NanAssignPersistent(each_baton->async->completed_cb, each_baton->completed); STATEMENT_BEGIN(Each); } @@ -664,10 +668,10 @@ void Statement::AsyncEach(uv_async_t* handle, int status) { break; } - Local cb = NanPersistentToLocal(async->item_cb); + Local cb = NanNew(async->item_cb); if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[2]; - argv[0] = NanNewLocal(Null()); + argv[0] = NanNew(NanNull()); Rows::const_iterator it = rows.begin(); Rows::const_iterator end = rows.end(); @@ -680,13 +684,13 @@ void Statement::AsyncEach(uv_async_t* handle, int status) { } } - Local cb = NanPersistentToLocal(async->completed_cb); + Local cb = NanNew(async->completed_cb); if (async->completed) { if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { - NanNewLocal(Null()), - Integer::New(async->retrieved) + NanNew(NanNull()), + NanNew(async->retrieved) }; TRY_CATCH_CALL(NanObjectWrapHandle(async->stmt), cb, 2, argv); } @@ -733,9 +737,9 @@ void Statement::Work_AfterReset(uv_work_t* req) { STATEMENT_INIT(Baton); // Fire callbacks. - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { - Local argv[] = { NanNewLocal(Null()) }; + Local argv[] = { NanNew(NanNull()) }; TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } @@ -743,7 +747,9 @@ void Statement::Work_AfterReset(uv_work_t* req) { } Local Statement::RowToJS(Row* row) { - Local result(Object::New()); + NanEscapableScope(); + + Local result(NanNew()); Row::const_iterator it = row->begin(); Row::const_iterator end = row->end(); @@ -754,28 +760,28 @@ Local Statement::RowToJS(Row* row) { switch (field->type) { case SQLITE_INTEGER: { - value = Local(Number::New(((Values::Integer*)field)->value)); + value = NanNew(((Values::Integer*)field)->value); } break; case SQLITE_FLOAT: { - value = Local(Number::New(((Values::Float*)field)->value)); + value = NanNew(((Values::Float*)field)->value); } break; case SQLITE_TEXT: { - value = Local(String::New(((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size())); + value = NanNew(((Values::Text*)field)->value.c_str(), ((Values::Text*)field)->value.size()); } break; case SQLITE_BLOB: { - value = NanNewLocal(NanNewBufferHandle(((Values::Blob*)field)->value, ((Values::Blob*)field)->length)); + value = NanNew(NanNewBufferHandle(((Values::Blob*)field)->value, ((Values::Blob*)field)->length)); } break; case SQLITE_NULL: { - value = NanNewLocal(Null()); + value = NanNew(NanNull()); } break; } - result->Set(String::NewSymbol(field->name.c_str()), value); + result->Set(NanNew(field->name.c_str()), value); DELETE_FIELD(field); } - return result; + return NanEscapeScope(result); } void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { @@ -822,10 +828,11 @@ NAN_METHOD(Statement::Finalize) { } void Statement::Finalize(Baton* baton) { + NanScope(); baton->stmt->Finalize(); // Fire callback in case there was one. - Local cb = NanPersistentToLocal(baton->callback); + Local cb = NanNew(baton->callback); if (!cb.IsEmpty() && cb->IsFunction()) { TRY_CATCH_CALL(NanObjectWrapHandle(baton->stmt), cb, 0, NULL); } @@ -845,10 +852,11 @@ void Statement::Finalize() { } void Statement::CleanQueue() { + NanScope(); 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(NanNew("Statement is already finalized"), SQLITE_MISUSE, exception); Local argv[] = { exception }; bool called = false; @@ -857,7 +865,7 @@ void Statement::CleanQueue() { Call* call = queue.front(); queue.pop(); - Local cb = NanPersistentToLocal(call->baton->callback); + Local cb = NanNew(call->baton->callback); if (prepared && !cb.IsEmpty() && cb->IsFunction()) { @@ -874,7 +882,7 @@ void Statement::CleanQueue() { // When we couldn't call a callback function, emit an error on the // Statement object. if (!called) { - Local args[] = { String::NewSymbol("error"), exception }; + Local args[] = { NanNew("error"), exception }; EMIT_EVENT(NanObjectWrapHandle(this), 2, args); } } diff --git a/src/statement.h b/src/statement.h index 2c50205de..b79d9847c 100644 --- a/src/statement.h +++ b/src/statement.h @@ -88,7 +88,7 @@ class Statement : public ObjectWrap { Baton(Statement* stmt_, Handle cb_) : stmt(stmt_) { stmt->Ref(); request.data = this; - NanAssignPersistent(Function, callback, cb_); + NanAssignPersistent(callback, cb_); } virtual ~Baton() { for (unsigned int i = 0; i < parameters.size(); i++) { @@ -96,7 +96,7 @@ class Statement : public ObjectWrap { DELETE_FIELD(field); } stmt->Unref(); - callback.Dispose(); + NanDisposePersistent(callback); } }; @@ -122,10 +122,14 @@ class Statement : public ObjectWrap { struct Async; struct EachBaton : Baton { - EachBaton(Statement* stmt_, Handle cb_) : - Baton(stmt_, cb_) {} Persistent completed; Async* async; // Isn't deleted when the baton is deleted. + + EachBaton(Statement* stmt_, Handle cb_) : + Baton(stmt_, cb_) {} + virtual ~EachBaton() { + NanDisposePersistent(completed); + } }; struct PrepareBaton : Database::Baton { @@ -176,8 +180,8 @@ class Statement : public ObjectWrap { ~Async() { stmt->Unref(); - item_cb.Dispose(); - completed_cb.Dispose(); + NanDisposePersistent(item_cb); + NanDisposePersistent(completed_cb); NODE_SQLITE3_MUTEX_DESTROY } }; diff --git a/test/named_columns.test.js b/test/named_columns.test.js index fcb8f2c08..9973bfcee 100644 --- a/test/named_columns.test.js +++ b/test/named_columns.test.js @@ -26,4 +26,13 @@ describe('named columns', function() { done(); }); }); + + it('should be able to retrieve rowid of last inserted value', function(done) { + db.get("SELECT last_insert_rowid() as last_id FROM foo", function(err, row) { + if (err) throw err; + assert.equal(row.last_id, 1); + done(); + }); + }); + }); diff --git a/test/nw/Makefile b/test/nw/Makefile index adb7dbfc9..9c8223301 100755 --- a/test/nw/Makefile +++ b/test/nw/Makefile @@ -3,10 +3,10 @@ NODE_WEBKIT_VERSION=0.8.4 all: app.nw node_modules/sqlite3: - npm install https://github.com/mapbox/node-sqlite3/tarball/master + npm install https://github.com/mapbox/node-sqlite3/tarball/master --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION) -node_modules/sqlite3/lib/node_sqlite3.node: node_modules/sqlite3 - cd node_modules/sqlite3 && nw-gyp rebuild --target=$(NODE_WEBKIT_VERSION) && rm -rf build/ +rebuild: + cd node_modules/sqlite3 && ./node_modules/.bin/node-pre-gyp rebuild --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION) node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip: wget https://s3.amazonaws.com/node-webkit/v$(NODE_WEBKIT_VERSION)/node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip @@ -14,7 +14,7 @@ node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip: ./node-webkit.app: node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip unzip -o node-webkit-v$(NODE_WEBKIT_VERSION)-osx-ia32.zip -app.nw: ./node-webkit.app Makefile package.json index.html node_modules/sqlite3/lib/node_sqlite3.node +app.nw: ./node-webkit.app Makefile package.json index.html node_modules/sqlite3 zip app.nw index.html package.json node_modules test: ./node-webkit.app app.nw @@ -30,8 +30,7 @@ package: ./node-webkit.app Makefile package.json index.html node_modules/sqlite3 ./node-sqlite-test.app/Contents/MacOS/node-webkit clean: - rm -rf ./node_modules/sqlite3/build - rm -f ./node_modules/sqlite3/lib/node_sqlite3.node + rm -rf ./node_modules/sqlite3 rm -f ./app.nw rm -rf node-sqlite-test.app rm -f credits.html diff --git a/test/prepare.test.js b/test/prepare.test.js index eb9889e75..c32db72a4 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 5dc29b465..6545f09c9 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); }); });