diff --git a/.travis.yml b/.travis.yml index c0ddce60c..1b46e3924 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ env: matrix: - export NODE_VERSION="0.8" - export NODE_VERSION="0.10" NODE_WEBKIT="0.8.6" + - export NODE_VERSION="0.11" global: - secure: QhuP5E/kYL1j1KDkHGJtk6DSJr1RH4DR/JrC62Viuf5Du8jE+i0kPWfF2MxtuEmKo35orhpu8t8mzKygWfuO63WPuuIE9qd/+V/y99Lqcj0tEN6wJ5RnywktbTJWg23zphjhmYq3Xj8DLVEikCZBwHtlbygkO9Q60cn1PK+bnPg= - secure: HxCS2dQAWI0KmCFnFNNZoucG4FeAW+itG7+Hp0dNtwmxZzGOZYFO2bZcGvTAMNfVN++oqLxTebYQI1oB5yUl5mPJjrjthaGS6Zq3S6rfJcXiv+icYgEXlR6ejQ97dsHw1Jeg8nedCQlI4kHfvG6pgBLhq9hnugxH1Cjhdt14E9U= diff --git a/binding.gyp b/binding.gyp index ca97c776e..e3a5a9636 100644 --- a/binding.gyp +++ b/binding.gyp @@ -7,6 +7,7 @@ "targets": [ { "target_name": "<(module_name)", + "include_dirs": ["", - "Dane Springmeyer ", - "Will White ", - "Orlando Vazquez ", - "Artem Kustikov ", - "Eric Fredricksen ", - "John Wright ", - "Ryan Dahl ", - "Tom MacWright ", - "Carter Thaxton ", - "Audrius Kažukauskas ", - "Johannes Schauer ", - "Nathan Rajlich ", - "AJ ONeal ", - "Mithgol" - ], - "repository": { - "type": "git", - "url": "git://github.com/mapbox/node-sqlite3.git" - }, - "dependencies": { - "node-pre-gyp": "0.5.13" - }, - "bundledDependencies": [ - "node-pre-gyp" - ], - "devDependencies": { - "mocha": "*" - }, - "engines": { - "node": ">= 0.8.0 < 0.11.0" - }, - "scripts": { - "install": "node-pre-gyp install --fallback-to-build", - "pretest": "node test/support/createdb.js", - "test": "mocha -R spec --timeout 200000" - }, - "licenses": [ - { - "type": "BSD" - } - ], - "main": "./lib/sqlite3" + "name": "sqlite3", + "description": "Asynchronous, non-blocking SQLite3 bindings", + "version": "2.2.3", + "homepage": "http://github.com/mapbox/node-sqlite3", + "author": { + "name": "MapBox", + "url": "https://mapbox.com/" + }, + "binary": { + "module_name": "node_sqlite3", + "module_path": "./lib/binding/{node_abi}-{platform}-{arch}", + "remote_path": "./{configuration}", + "package_name": "{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz", + "host": "https://node-sqlite3.s3.amazonaws.com" + }, + "contributors": [ + "Konstantin Käfer ", + "Dane Springmeyer ", + "Will White ", + "Orlando Vazquez ", + "Artem Kustikov ", + "Eric Fredricksen ", + "John Wright ", + "Ryan Dahl ", + "Tom MacWright ", + "Carter Thaxton ", + "Audrius Kažukauskas ", + "Johannes Schauer ", + "Nathan Rajlich ", + "AJ ONeal ", + "Mithgol" + ], + "repository": { + "type": "git", + "url": "git://github.com/mapbox/node-sqlite3.git" + }, + "dependencies": { + "nan": "1.1.2", + "node-pre-gyp": "0.5.13", + "set-immediate": "0.1.1" + }, + "bundledDependencies": [ + "node-pre-gyp" + ], + "devDependencies": { + "mocha": "*" + }, + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "install": "node-pre-gyp install --fallback-to-build", + "pretest": "node test/support/createdb.js", + "test": "mocha -R spec --timeout 200000 -s 20000" + }, + "licenses": [ + { + "type": "BSD" + } + ], + "main": "./lib/sqlite3" } 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 50206e6c6..27e4252e9 100644 --- a/src/database.cc +++ b/src/database.cc @@ -10,39 +10,43 @@ using namespace node_sqlite3; Persistent Database::constructor_template; void Database::Init(Handle target) { - HandleScope scope; + NanScope(); - Local t = FunctionTemplate::New(New); + Local t = NanNew(New); - constructor_template = Persistent::New(t); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); - constructor_template->SetClassName(String::NewSymbol("Database")); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("Database")); - 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); + NODE_SET_PROTOTYPE_METHOD(t, "close", Close); + NODE_SET_PROTOTYPE_METHOD(t, "exec", Exec); + NODE_SET_PROTOTYPE_METHOD(t, "wait", Wait); + NODE_SET_PROTOTYPE_METHOD(t, "loadExtension", LoadExtension); + NODE_SET_PROTOTYPE_METHOD(t, "serialize", Serialize); + NODE_SET_PROTOTYPE_METHOD(t, "parallelize", Parallelize); + NODE_SET_PROTOTYPE_METHOD(t, "configure", Configure); - NODE_SET_GETTER(constructor_template, "open", OpenGetter); + NODE_SET_GETTER(t, "open", OpenGetter); - target->Set(String::NewSymbol("Database"), - constructor_template->GetFunction()); + NanAssignPersistent(constructor_template, t); + + 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(); - if (!call->baton->callback.IsEmpty() && call->baton->callback->IsFunction()) { - TRY_CATCH_CALL(handle_, call->baton->callback, 1, argv); + Local cb = NanNew(call->baton->callback); + if (!cb.IsEmpty() && cb->IsFunction()) { + TRY_CATCH_CALL(NanObjectWrapHandle(this), cb, 1, argv); called = true; } queue.pop(); @@ -55,8 +59,8 @@ 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 }; - EMIT_EVENT(handle_, 2, args); + Local args[] = { NanNew("error"), exception }; + EMIT_EVENT(NanObjectWrapHandle(this), 2, args); } return; } @@ -78,15 +82,17 @@ 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); - if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { + EXCEPTION(NanNew("Database is closed"), SQLITE_MISUSE, exception); + Local cb = NanNew(baton->callback); + if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { exception }; - TRY_CATCH_CALL(handle_, baton->callback, 1, argv); + TRY_CATCH_CALL(NanObjectWrapHandle(this), cb, 1, argv); } else { - Local argv[] = { String::NewSymbol("error"), exception }; - EMIT_EVENT(handle_, 2, argv); + Local argv[] = { NanNew("error"), exception }; + EMIT_EVENT(NanObjectWrapHandle(this), 2, argv); } return; } @@ -100,13 +106,11 @@ void Database::Schedule(Work_Callback callback, Baton* baton, bool exclusive) { } } -Handle Database::New(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Database::New) { + NanScope(); if (!args.IsConstructCall()) { - return ThrowException(Exception::TypeError( - String::New("Use the new operator to create new Database objects")) - ); + return NanThrowTypeError("Use the new operator to create new Database objects"); } REQUIRE_ARGUMENT_STRING(0, filename); @@ -127,14 +131,14 @@ Handle Database::New(const Arguments& args) { 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()->Set(NanNew("filename"), args[0]->ToString(), ReadOnly); + args.This()->Set(NanNew("mode"), NanNew(mode), ReadOnly); // Start opening the database. OpenBaton* baton = new OpenBaton(db, callback, *filename, mode); Work_BeginOpen(baton); - return args.This(); + NanReturnValue(args.This()); } void Database::Work_BeginOpen(Baton* baton) { @@ -149,75 +153,77 @@ 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; + NanScope(); OpenBaton* baton = static_cast(req->data); Database* db = baton->db; 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] = Local::New(Null()); + argv[0] = NanNew(NanNull()); } - if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { - TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); + 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] }; - EMIT_EVENT(db->handle_, 2, args); + Local args[] = { NanNew("error"), argv[0] }; + EMIT_EVENT(NanObjectWrapHandle(db), 2, args); } if (db->open) { - Local args[] = { String::NewSymbol("open") }; - EMIT_EVENT(db->handle_, 1, args); + Local args[] = { NanNew("open") }; + EMIT_EVENT(NanObjectWrapHandle(db), 1, args); db->Process(); } delete baton; } -Handle Database::OpenGetter(Local str, const AccessorInfo& accessor) { - HandleScope scope; - Database* db = ObjectWrap::Unwrap(accessor.This()); - return Boolean::New(db->open); +NAN_GETTER(Database::OpenGetter) { + NanScope(); + Database* db = ObjectWrap::Unwrap(args.This()); + NanReturnValue(NanNew(db->open)); } -Handle Database::Close(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Database::Close) { + NanScope(); Database* db = ObjectWrap::Unwrap(args.This()); OPTIONAL_ARGUMENT_FUNCTION(0, callback); Baton* baton = new Baton(db, callback); db->Schedule(Work_BeginClose, baton, true); - return args.This(); + NanReturnValue(args.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,53 +236,55 @@ void Database::Work_Close(uv_work_t* req) { Baton* baton = static_cast(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; + NanScope(); Baton* baton = static_cast(req->data); Database* db = baton->db; 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] = Local::New(Null()); + argv[0] = NanNew(NanNull()); } + Local cb = NanNew(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(NanObjectWrapHandle(db), cb, 1, argv); } else if (db->open) { - Local args[] = { String::NewSymbol("error"), argv[0] }; - EMIT_EVENT(db->handle_, 2, args); + Local args[] = { NanNew("error"), argv[0] }; + EMIT_EVENT(NanObjectWrapHandle(db), 2, args); } if (!db->open) { - Local args[] = { String::NewSymbol("close"), argv[0] }; - EMIT_EVENT(db->handle_, 1, args); + Local args[] = { NanNew("close"), argv[0] }; + EMIT_EVENT(NanObjectWrapHandle(db), 1, args); db->Process(); } delete baton; } -Handle Database::Serialize(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Database::Serialize) { + NanScope(); Database* db = ObjectWrap::Unwrap(args.This()); OPTIONAL_ARGUMENT_FUNCTION(0, callback); @@ -290,11 +298,11 @@ Handle Database::Serialize(const Arguments& args) { db->Process(); - return args.This(); + NanReturnValue(args.This()); } -Handle Database::Parallelize(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Database::Parallelize) { + NanScope(); Database* db = ObjectWrap::Unwrap(args.This()); OPTIONAL_ARGUMENT_FUNCTION(0, callback); @@ -308,30 +316,28 @@ Handle Database::Parallelize(const Arguments& args) { db->Process(); - return args.This(); + NanReturnValue(args.This()); } -Handle Database::Configure(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Database::Configure) { + NanScope(); Database* db = ObjectWrap::Unwrap(args.This()); 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 ThrowException(Exception::TypeError( - String::New("Value must be an integer")) - ); + return NanThrowTypeError("Value must be an integer"); } Local handle; Baton* baton = new Baton(db, handle); @@ -339,40 +345,40 @@ Handle Database::Configure(const Arguments& args) { db->Schedule(SetBusyTimeout, baton); } else { - return ThrowException(Exception::Error(String::Concat( + return NanThrowError(Exception::Error(String::Concat( args[0]->ToString(), - String::NewSymbol(" is not a valid configuration option") + NanNew(" is not a valid configuration option") ))); } db->Process(); - return args.This(); + NanReturnValue(args.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 +394,28 @@ 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; + NanScope(); Local argv[] = { - String::NewSymbol("trace"), - String::New(sql->c_str()) + NanNew("trace"), + NanNew(sql->c_str()) }; - EMIT_EVENT(db->handle_, 2, argv); + EMIT_EVENT(NanObjectWrapHandle(db), 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 +433,29 @@ void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs) } void Database::ProfileCallback(Database *db, ProfileInfo* info) { - HandleScope scope; + 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(db->handle_, 3, argv); + EMIT_EVENT(NanObjectWrapHandle(db), 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,20 +476,20 @@ void Database::UpdateCallback(void* db, int type, const char* database, } void Database::UpdateCallback(Database *db, UpdateInfo* info) { - HandleScope scope; + 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(db->handle_, 4, argv); + EMIT_EVENT(NanObjectWrapHandle(db), 4, argv); delete info; } -Handle Database::Exec(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Database::Exec) { + NanScope(); Database* db = ObjectWrap::Unwrap(args.This()); REQUIRE_ARGUMENT_STRING(0, sql); @@ -492,13 +498,13 @@ Handle Database::Exec(const Arguments& args) { Baton* baton = new ExecBaton(db, callback, *sql); db->Schedule(Work_BeginExec, baton, true); - return args.This(); + NanReturnValue(args.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 +516,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 +530,27 @@ void Database::Work_Exec(uv_work_t* req) { } void Database::Work_AfterExec(uv_work_t* req) { - HandleScope scope; + NanScope(); ExecBaton* baton = static_cast(req->data); Database* db = baton->db; + 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 (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { + if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { exception }; - TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); + TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } else { - Local args[] = { String::NewSymbol("error"), exception }; - EMIT_EVENT(db->handle_, 2, args); + Local args[] = { NanNew("error"), exception }; + EMIT_EVENT(NanObjectWrapHandle(db), 2, args); } } - else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { - Local argv[] = { Local::New(Null()) }; - TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); + else if (!cb.IsEmpty() && cb->IsFunction()) { + Local argv[] = { NanNew(NanNull()) }; + TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } db->Process(); @@ -551,8 +558,8 @@ void Database::Work_AfterExec(uv_work_t* req) { delete baton; } -Handle Database::Wait(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Database::Wait) { + NanScope(); Database* db = ObjectWrap::Unwrap(args.This()); OPTIONAL_ARGUMENT_FUNCTION(0, callback); @@ -560,20 +567,21 @@ Handle Database::Wait(const Arguments& args) { Baton* baton = new Baton(db, callback); db->Schedule(Work_Wait, baton, true); - return args.This(); + NanReturnValue(args.This()); } void Database::Work_Wait(Baton* baton) { - HandleScope scope; + NanScope(); 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 argv[] = { Local::New(Null()) }; - TRY_CATCH_CALL(baton->db->handle_, baton->callback, 1, argv); + Local cb = NanNew(baton->callback); + if (!cb.IsEmpty() && cb->IsFunction()) { + Local argv[] = { NanNew(NanNull()) }; + TRY_CATCH_CALL(NanObjectWrapHandle(baton->db), cb, 1, argv); } baton->db->Process(); @@ -581,8 +589,8 @@ void Database::Work_Wait(Baton* baton) { delete baton; } -Handle Database::LoadExtension(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Database::LoadExtension) { + NanScope(); Database* db = ObjectWrap::Unwrap(args.This()); REQUIRE_ARGUMENT_STRING(0, filename); @@ -591,13 +599,13 @@ Handle Database::LoadExtension(const Arguments& args) { Baton* baton = new LoadExtensionBaton(db, callback, *filename); db->Schedule(Work_BeginLoadExtension, baton, true); - return args.This(); + NanReturnValue(args.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); @@ -607,17 +615,17 @@ void Database::Work_BeginLoadExtension(Baton* baton) { void Database::Work_LoadExtension(uv_work_t* req) { LoadExtensionBaton* baton = static_cast(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 +634,26 @@ void Database::Work_LoadExtension(uv_work_t* req) { } void Database::Work_AfterLoadExtension(uv_work_t* req) { - HandleScope scope; + NanScope(); LoadExtensionBaton* baton = static_cast(req->data); Database* db = baton->db; + 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 (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { + if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { exception }; - TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); + TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } else { - Local args[] = { String::NewSymbol("error"), exception }; - EMIT_EVENT(db->handle_, 2, args); + Local args[] = { NanNew("error"), exception }; + EMIT_EVENT(NanObjectWrapHandle(db), 2, args); } } - else if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { - Local argv[] = { Local::New(Null()) }; - TRY_CATCH_CALL(db->handle_, baton->callback, 1, argv); + else if (!cb.IsEmpty() && cb->IsFunction()) { + Local argv[] = { NanNew(NanNull()) }; + TRY_CATCH_CALL(NanObjectWrapHandle(db), cb, 1, argv); } db->Process(); diff --git a/src/database.h b/src/database.h index a051dae2a..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 @@ -7,6 +8,7 @@ #include #include +#include "nan.h" #include "async.h" using namespace v8; @@ -23,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 constructor_template->HasInstance(obj); + return NanNew(constructor_template)->HasInstance(obj); } struct Baton { @@ -39,11 +42,11 @@ class Database : public ObjectWrap { db(db_), status(SQLITE_OK) { db->Ref(); request.data = this; - callback = Persistent::New(cb_); + NanAssignPersistent(callback, cb_); } virtual ~Baton() { db->Unref(); - callback.Dispose(); + NanDisposePersistent(callback); } }; @@ -99,7 +102,7 @@ class Database : public ObjectWrap { protected: Database() : ObjectWrap(), - handle(NULL), + _handle(NULL), open(false), locked(false), pending(0), @@ -107,48 +110,47 @@ class Database : public ObjectWrap { debug_trace(NULL), debug_profile(NULL), update_event(NULL) { - } ~Database() { RemoveCallbacks(); - sqlite3_close(handle); - handle = NULL; + sqlite3_close(_handle); + _handle = NULL; open = false; } - static Handle 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 OpenGetter(Local str, const AccessorInfo& accessor); + static NAN_GETTER(OpenGetter); void Schedule(Work_Callback callback, Baton* baton, bool exclusive = false); void Process(); - static Handle 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 Wait(const Arguments& args); + static NAN_METHOD(Wait); static void Work_Wait(Baton* baton); - static Handle 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 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 Serialize(const Arguments& args); - static Handle Parallelize(const Arguments& args); + static NAN_METHOD(Serialize); + static NAN_METHOD(Parallelize); - static Handle Configure(const Arguments& args); + static NAN_METHOD(Configure); static void SetBusyTimeout(Baton* baton); @@ -167,7 +169,7 @@ class Database : public ObjectWrap { void RemoveCallbacks(); protected: - sqlite3* handle; + sqlite3* _handle; bool open; bool locked; diff --git a/src/macros.h b/src/macros.h index dbd14d0c3..c98a86bf2 100644 --- a/src/macros.h +++ b/src/macros.h @@ -7,35 +7,27 @@ const char* sqlite_authorizer_string(int type); #define REQUIRE_ARGUMENTS(n) \ if (args.Length() < (n)) { \ - return ThrowException( \ - Exception::TypeError(String::New("Expected " #n "arguments")) \ - ); \ + return NanThrowTypeError("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")) \ - ); \ + return NanThrowTypeError("Argument " #i " invalid"); \ } \ Local var = Local::Cast(args[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")) \ - ); \ + return NanThrowTypeError("Argument " #i " must be a function"); \ } \ Local var = Local::Cast(args[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")) \ - ); \ + return NanThrowTypeError("Argument " #i " must be a string"); \ } \ String::Utf8Value var(args[i]->ToString()); @@ -44,9 +36,7 @@ const char* sqlite_authorizer_string(int type); Local var; \ if (args.Length() > i && !args[i]->IsUndefined()) { \ if (!args[i]->IsFunction()) { \ - return ThrowException(Exception::TypeError( \ - String::New("Argument " #i " must be a function")) \ - ); \ + return NanThrowTypeError("Argument " #i " must be a function"); \ } \ var = Local::Cast(args[i]); \ } @@ -61,68 +51,62 @@ const char* sqlite_authorizer_string(int type); var = args[i]->Int32Value(); \ } \ else { \ - return ThrowException(Exception::TypeError( \ - String::New("Argument " #i " must be an integer")) \ - ); \ + return NanThrowTypeError("Argument " #i " must be an integer"); \ } #define DEFINE_CONSTANT_INTEGER(target, constant, name) \ (target)->Set( \ - String::NewSymbol(#name), \ - Integer::New(constant), \ + NanNew(#name), \ + NanNew(constant), \ static_cast(ReadOnly | DontDelete) \ ); #define DEFINE_CONSTANT_STRING(target, constant, name) \ (target)->Set( \ - String::NewSymbol(#name), \ - String::NewSymbol(constant), \ + 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(NODE_PSYMBOL("errno"), Integer::New(errno)); \ - name ##_obj->Set(NODE_PSYMBOL("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; \ - (callback)->Call((context), (argc), (argv)); \ - if (try_catch.HasCaught()) { \ - FatalException(try_catch); \ - } } - -#define WORK_DEFINITION(name) \ - static Handle name(const Arguments& args); \ + NanMakeCallback((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); @@ -164,4 +148,3 @@ const char* sqlite_authorizer_string(int type); } #endif - diff --git a/src/node_sqlite3.cc b/src/node_sqlite3.cc index b588bbd90..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); @@ -103,4 +104,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 86df3152e..e60d96d97 100644 --- a/src/statement.cc +++ b/src/statement.cc @@ -12,24 +12,24 @@ using namespace node_sqlite3; Persistent Statement::constructor_template; void Statement::Init(Handle target) { - HandleScope scope; + NanScope(); - Local t = FunctionTemplate::New(New); + Local t = NanNew(New); - constructor_template = Persistent::New(t); - constructor_template->InstanceTemplate()->SetInternalFieldCount(1); - constructor_template->SetClassName(String::NewSymbol("Statement")); + t->InstanceTemplate()->SetInternalFieldCount(1); + t->SetClassName(NanNew("Statement")); - 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); + NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind); + NODE_SET_PROTOTYPE_METHOD(t, "get", Get); + NODE_SET_PROTOTYPE_METHOD(t, "run", Run); + NODE_SET_PROTOTYPE_METHOD(t, "all", All); + NODE_SET_PROTOTYPE_METHOD(t, "each", Each); + NODE_SET_PROTOTYPE_METHOD(t, "reset", Reset); + NODE_SET_PROTOTYPE_METHOD(t, "finalize", Finalize); - target->Set(String::NewSymbol("Statement"), - constructor_template->GetFunction()); + NanAssignPersistent(constructor_template, t); + target->Set(NanNew("Statement"), + t->GetFunction()); } void Statement::Process() { @@ -60,50 +60,49 @@ 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 = NanNew(baton->callback); - if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { + if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[] = { exception }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } else { - Local argv[] = { String::NewSymbol("error"), exception }; - EMIT_EVENT(stmt->handle_, 2, argv); + Local argv[] = { NanNew("error"), exception }; + EMIT_EVENT(NanObjectWrapHandle(stmt), 2, argv); } } // { Database db, String sql, Array params, Function callback } -Handle Statement::New(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Statement::New) { + NanScope(); if (!args.IsConstructCall()) { - return ThrowException(Exception::TypeError( - String::New("Use the new operator to create new Statement objects")) - ); + return NanThrowTypeError("Use the new operator to create new Statement objects"); } int length = args.Length(); if (length <= 0 || !Database::HasInstance(args[0])) { - return ThrowException(Exception::TypeError( - String::New("Database object expected"))); + return NanThrowTypeError("Database object expected"); } else if (length <= 1 || !args[1]->IsString()) { - return ThrowException(Exception::TypeError( - String::New("SQL query expected"))); + return NanThrowTypeError("SQL query expected"); } else if (length > 2 && !args[2]->IsUndefined() && !args[2]->IsFunction()) { - return ThrowException(Exception::TypeError( - String::New("Callback expected"))); + return NanThrowTypeError("Callback expected"); } Database* db = ObjectWrap::Unwrap(args[0]->ToObject()); Local sql = Local::Cast(args[1]); - args.This()->Set(String::NewSymbol("sql"), sql, ReadOnly); + args.This()->Set(NanNew("sql"), sql, ReadOnly); Statement* stmt = new Statement(db); stmt->Wrap(args.This()); @@ -112,7 +111,7 @@ Handle Statement::New(const Arguments& args) { baton->sql = std::string(*String::Utf8Value(sql)); db->Schedule(Work_BeginPrepare, baton); - return args.This(); + NanReturnValue(args.This()); } void Statement::Work_BeginPrepare(Database::Baton* baton) { @@ -128,27 +127,27 @@ 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; + NanScope(); STATEMENT_INIT(PrepareBaton); if (stmt->status != SQLITE_OK) { @@ -157,9 +156,10 @@ void Statement::Work_AfterPrepare(uv_work_t* req) { } else { stmt->prepared = true; - if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { - Local argv[] = { Local::New(Null()) }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); + Local cb = NanNew(baton->callback); + if (!cb.IsEmpty() && cb->IsFunction()) { + Local argv[] = { NanNew(NanNull()) }; + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } } @@ -196,7 +196,9 @@ template Values::Field* } } -template T* Statement::Bind(const Arguments& args, int start, int last) { +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()) { @@ -252,8 +254,8 @@ bool Statement::Bind(const Parameters & parameters) { return true; } - sqlite3_reset(handle); - sqlite3_clear_bindings(handle); + sqlite3_reset(_handle); + sqlite3_clear_bindings(_handle); Parameters::const_iterator it = parameters.begin(); Parameters::const_iterator end = parameters.end(); @@ -267,36 +269,36 @@ 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)); + message = std::string(sqlite3_errmsg(db->_handle)); return false; } } @@ -304,17 +306,17 @@ bool Statement::Bind(const Parameters & parameters) { return true; } -Handle Statement::Bind(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Statement::Bind) { + NanScope(); Statement* stmt = ObjectWrap::Unwrap(args.This()); Baton* baton = stmt->Bind(args); if (baton == NULL) { - return ThrowException(Exception::Error(String::New("Data type is not supported"))); + return NanThrowTypeError("Data type is not supported"); } else { stmt->Schedule(Work_BeginBind, baton); - return args.This(); + NanReturnValue(args.This()); } } @@ -325,14 +327,14 @@ 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; + NanScope(); STATEMENT_INIT(Baton); if (stmt->status != SQLITE_OK) { @@ -340,9 +342,10 @@ void Statement::Work_AfterBind(uv_work_t* req) { } else { // Fire callbacks. - if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { - Local argv[] = { Local::New(Null()) }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); + Local cb = NanNew(baton->callback); + if (!cb.IsEmpty() && cb->IsFunction()) { + Local argv[] = { NanNew(NanNull()) }; + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } } @@ -351,17 +354,17 @@ void Statement::Work_AfterBind(uv_work_t* req) { -Handle Statement::Get(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Statement::Get) { + NanScope(); Statement* stmt = ObjectWrap::Unwrap(args.This()); Baton* baton = stmt->Bind(args); if (baton == NULL) { - return ThrowException(Exception::Error(String::New("Data type is not supported"))); + return NanThrowError("Data type is not supported"); } else { stmt->Schedule(Work_BeginGet, baton); - return args.This(); + NanReturnValue(args.This()); } } @@ -373,14 +376,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 +391,13 @@ 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; + NanScope(); STATEMENT_INIT(RowBaton); if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { @@ -402,15 +405,16 @@ void Statement::Work_AfterGet(uv_work_t* req) { } else { // Fire callbacks. - if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { + 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[] = { Local::New(Null()), RowToJS(&baton->row) }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv); + Local argv[] = { NanNew(NanNull()), RowToJS(&baton->row) }; + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv); } else { - Local argv[] = { Local::New(Null()) }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); + Local argv[] = { NanNew(NanNull()) }; + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } } } @@ -418,17 +422,17 @@ void Statement::Work_AfterGet(uv_work_t* req) { STATEMENT_END(); } -Handle Statement::Run(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Statement::Run) { + NanScope(); Statement* stmt = ObjectWrap::Unwrap(args.This()); Baton* baton = stmt->Bind(args); if (baton == NULL) { - return ThrowException(Exception::Error(String::New("Data type is not supported"))); + return NanThrowError("Data type is not supported"); } else { stmt->Schedule(Work_BeginRun, baton); - return args.This(); + NanReturnValue(args.This()); } } @@ -439,23 +443,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 +467,7 @@ void Statement::Work_Run(uv_work_t* req) { } void Statement::Work_AfterRun(uv_work_t* req) { - HandleScope scope; + NanScope(); STATEMENT_INIT(RunBaton); if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) { @@ -471,29 +475,30 @@ 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::New(baton->inserted_id))); - stmt->handle_->Set(String::NewSymbol("changes"), Local(Integer::New(baton->changes))); + Local cb = NanNew(baton->callback); + if (!cb.IsEmpty() && cb->IsFunction()) { + NanObjectWrapHandle(stmt)->Set(NanNew("lastID"), NanNew(baton->inserted_id)); + NanObjectWrapHandle(stmt)->Set(NanNew("changes"), NanNew(baton->changes)); - Local argv[] = { Local::New(Null()) }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); + Local argv[] = { NanNew(NanNull()) }; + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } } STATEMENT_END(); } -Handle Statement::All(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Statement::All) { + NanScope(); Statement* stmt = ObjectWrap::Unwrap(args.This()); Baton* baton = stmt->Bind(args); if (baton == NULL) { - return ThrowException(Exception::Error(String::New("Data type is not supported"))); + return NanThrowError("Data type is not supported"); } else { stmt->Schedule(Work_BeginAll, baton); - return args.This(); + NanReturnValue(args.This()); } } @@ -504,23 +509,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 +533,7 @@ void Statement::Work_All(uv_work_t* req) { } void Statement::Work_AfterAll(uv_work_t* req) { - HandleScope scope; + NanScope(); STATEMENT_INIT(RowsBaton); if (stmt->status != SQLITE_DONE) { @@ -536,10 +541,11 @@ void Statement::Work_AfterAll(uv_work_t* req) { } else { // Fire callbacks. - if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { + 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++) { @@ -547,16 +553,16 @@ void Statement::Work_AfterAll(uv_work_t* req) { delete *it; } - Local argv[] = { Local::New(Null()), result }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv); + Local argv[] = { NanNew(NanNull()), result }; + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv); } else { // There were no result rows. Local argv[] = { - Local::New(Null()), - Local::New(Array::New(0)) + NanNew(NanNull()), + NanNew(0) }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv); + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 2, argv); } } } @@ -564,8 +570,8 @@ void Statement::Work_AfterAll(uv_work_t* req) { STATEMENT_END(); } -Handle Statement::Each(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Statement::Each) { + NanScope(); Statement* stmt = ObjectWrap::Unwrap(args.This()); int last = args.Length(); @@ -577,12 +583,12 @@ Handle Statement::Each(const Arguments& args) { EachBaton* baton = stmt->Bind(args, 0, last); if (baton == NULL) { - return ThrowException(Exception::Error(String::New("Data type is not supported"))); + return NanThrowError("Data type is not supported"); } else { - baton->completed = Persistent::New(completed); + NanAssignPersistent(baton->completed, completed); stmt->Schedule(Work_BeginEach, baton); - return args.This(); + NanReturnValue(args.This()); } } @@ -590,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); - each_baton->async->item_cb = Persistent::New(each_baton->callback); - each_baton->async->completed_cb = Persistent::New(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); } @@ -602,23 +608,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 +634,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 +654,7 @@ void Statement::CloseCallback(uv_handle_t* handle) { } void Statement::AsyncEach(uv_async_t* handle, int status) { - HandleScope scope; + NanScope(); Async* async = static_cast(handle->data); while (true) { @@ -662,36 +668,38 @@ void Statement::AsyncEach(uv_async_t* handle, int status) { break; } - if (!async->item_cb.IsEmpty() && async->item_cb->IsFunction()) { + Local cb = NanNew(async->item_cb); + if (!cb.IsEmpty() && cb->IsFunction()) { Local argv[2]; - argv[0] = Local::New(Null()); + argv[0] = NanNew(NanNull()); 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(NanObjectWrapHandle(async->stmt), cb, 2, argv); delete *it; } } } + Local cb = NanNew(async->completed_cb); if (async->completed) { - if (!async->completed_cb.IsEmpty() && - async->completed_cb->IsFunction()) { + if (!cb.IsEmpty() && + cb->IsFunction()) { Local argv[] = { - Local::New(Null()), - Integer::New(async->retrieved) + NanNew(NanNull()), + NanNew(async->retrieved) }; - TRY_CATCH_CALL(async->stmt->handle_, async->completed_cb, 2, argv); + TRY_CATCH_CALL(NanObjectWrapHandle(async->stmt), cb, 2, argv); } uv_close((uv_handle_t*)handle, CloseCallback); } } void Statement::Work_AfterEach(uv_work_t* req) { - HandleScope scope; + NanScope(); STATEMENT_INIT(EachBaton); if (stmt->status != SQLITE_DONE) { @@ -701,8 +709,8 @@ void Statement::Work_AfterEach(uv_work_t* req) { STATEMENT_END(); } -Handle Statement::Reset(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Statement::Reset) { + NanScope(); Statement* stmt = ObjectWrap::Unwrap(args.This()); OPTIONAL_ARGUMENT_FUNCTION(0, callback); @@ -710,7 +718,7 @@ Handle Statement::Reset(const Arguments& args) { Baton* baton = new Baton(stmt, callback); stmt->Schedule(Work_BeginReset, baton); - return args.This(); + NanReturnValue(args.This()); } void Statement::Work_BeginReset(Baton* baton) { @@ -720,25 +728,28 @@ 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; + NanScope(); STATEMENT_INIT(Baton); // Fire callbacks. - if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) { - Local argv[] = { Local::New(Null()) }; - TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv); + Local cb = NanNew(baton->callback); + if (!cb.IsEmpty() && cb->IsFunction()) { + Local argv[] = { NanNew(NanNull()) }; + TRY_CATCH_CALL(NanObjectWrapHandle(stmt), cb, 1, argv); } STATEMENT_END(); } 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(); @@ -749,32 +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: { -#if NODE_VERSION_AT_LEAST(0, 11, 3) - value = Local::New(Buffer::New(((Values::Blob*)field)->value, ((Values::Blob*)field)->length)); -#else - value = Local::New(Buffer::New(((Values::Blob*)field)->value, ((Values::Blob*)field)->length)->handle_); -#endif + value = NanNew(NanNewBufferHandle(((Values::Blob*)field)->value, ((Values::Blob*)field)->length)); } break; case SQLITE_NULL: { - value = Local::New(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) { @@ -809,23 +816,25 @@ void Statement::GetRow(Row* row, sqlite3_stmt* stmt) { } } -Handle Statement::Finalize(const Arguments& args) { - HandleScope scope; +NAN_METHOD(Statement::Finalize) { + NanScope(); Statement* stmt = ObjectWrap::Unwrap(args.This()); OPTIONAL_ARGUMENT_FUNCTION(0, callback); Baton* baton = new Baton(stmt, callback); stmt->Schedule(Finalize, baton); - return stmt->db->handle_; + NanReturnValue(NanObjectWrapHandle(stmt->db)); } void Statement::Finalize(Baton* baton) { + NanScope(); 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 cb = NanNew(baton->callback); + if (!cb.IsEmpty() && cb->IsFunction()) { + TRY_CATCH_CALL(NanObjectWrapHandle(baton->stmt), cb, 0, NULL); } delete baton; @@ -837,16 +846,17 @@ 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() { + 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; @@ -855,9 +865,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 cb = NanNew(call->baton->callback); + + if (prepared && !cb.IsEmpty() && + cb->IsFunction()) { + TRY_CATCH_CALL(NanObjectWrapHandle(this), cb, 1, argv); called = true; } @@ -870,8 +882,8 @@ 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 }; - EMIT_EVENT(handle_, 2, args); + Local args[] = { NanNew("error"), exception }; + EMIT_EVENT(NanObjectWrapHandle(this), 2, args); } } else while (!queue.empty()) { diff --git a/src/statement.h b/src/statement.h index 3b02677d7..c708e7fe2 100644 --- a/src/statement.h +++ b/src/statement.h @@ -13,6 +13,7 @@ #include #include +#include "nan.h" using namespace v8; using namespace node; @@ -76,7 +77,7 @@ class Statement : public ObjectWrap { static Persistent constructor_template; static void Init(Handle target); - static Handle New(const Arguments& args); + static NAN_METHOD(New); struct Baton { uv_work_t request; @@ -87,7 +88,7 @@ class Statement : public ObjectWrap { Baton(Statement* stmt_, Handle cb_) : stmt(stmt_) { stmt->Ref(); request.data = this; - callback = Persistent::New(cb_); + NanAssignPersistent(callback, cb_); } virtual ~Baton() { for (unsigned int i = 0; i < parameters.size(); i++) { @@ -95,7 +96,7 @@ class Statement : public ObjectWrap { DELETE_FIELD(field); } stmt->Unref(); - callback.Dispose(); + NanDisposePersistent(callback); } }; @@ -175,15 +176,15 @@ class Statement : public ObjectWrap { ~Async() { stmt->Unref(); - item_cb.Dispose(); - completed_cb.Dispose(); + NanDisposePersistent(item_cb); + NanDisposePersistent(completed_cb); NODE_SQLITE3_MUTEX_DESTROY } }; Statement(Database* db_) : ObjectWrap(), db(db_), - handle(NULL), + _handle(NULL), status(SQLITE_OK), prepared(false), locked(true), @@ -202,7 +203,7 @@ class Statement : public ObjectWrap { WORK_DEFINITION(Each); WORK_DEFINITION(Reset); - static Handle Finalize(const Arguments& args); + static NAN_METHOD(Finalize); protected: static void Work_BeginPrepare(Database::Baton* baton); @@ -216,8 +217,8 @@ class Statement : public ObjectWrap { void Finalize(); template inline Values::Field* BindParameter(const Handle source, T pos); - template T* Bind(const Arguments& args, int start = 0, int end = -1); - bool Bind(const Parameters & parameters); + template T* Bind(_NAN_METHOD_ARGS, int start = 0, int end = -1); + bool Bind(const Parameters ¶meters); static void GetRow(Row* row, sqlite3_stmt* stmt); static Local RowToJS(Row* row); @@ -229,7 +230,7 @@ class Statement : public ObjectWrap { protected: Database* db; - sqlite3_stmt* handle; + sqlite3_stmt* _handle; int status; std::string message; diff --git a/test/profile.test.js b/test/profile.test.js index 5dc29b465..a8caeb27d 100644 --- a/test/profile.test.js +++ b/test/profile.test.js @@ -1,5 +1,6 @@ var sqlite3 = require('..'); var assert = require('assert'); +require('set-immediate'); describe('profiling', function() { var create = false; @@ -14,6 +15,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 +33,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 +45,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); }); });