better-sqlite3
Advanced tools
+1
-1
@@ -22,3 +22,3 @@ #!/usr/bin/env bash | ||
| YEAR="2026" | ||
| VERSION="3530300" | ||
| VERSION="3530400" | ||
@@ -25,0 +25,0 @@ # Defines below are sorted alphabetically |
@@ -58,3 +58,3 @@ 'use strict'; | ||
| let columns = def.columns; | ||
| if (!Array.isArray(columns) || !(columns = [...columns]).every(x => typeof x === 'string')) { | ||
| if (!Array.isArray(columns) || !isStringArray(columns = [...columns])) { | ||
| throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`); | ||
@@ -73,3 +73,3 @@ } | ||
| parameters = def.parameters; | ||
| if (!Array.isArray(parameters) || !(parameters = [...parameters]).every(x => typeof x === 'string')) { | ||
| if (!Array.isArray(parameters) || !isStringArray(parameters = [...parameters])) { | ||
| throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`); | ||
@@ -192,1 +192,7 @@ } | ||
| const defer = x => () => x; | ||
| const isStringArray = (arr) => { | ||
| for (let i = 0; i < arr.length; ++i) { | ||
| if (typeof arr[i] !== 'string') return false; | ||
| } | ||
| return true; | ||
| }; |
+2
-1
| { | ||
| "name": "better-sqlite3", | ||
| "version": "13.0.1", | ||
| "version": "13.0.2", | ||
| "description": "The fastest and simplest library for SQLite in Node.js.", | ||
@@ -31,2 +31,3 @@ "homepage": "http://github.com/WiseLibs/better-sqlite3", | ||
| ], | ||
| "gypfile": false, | ||
| "engines": { | ||
@@ -33,0 +34,0 @@ "node": ">=22" |
+1
-1
@@ -35,3 +35,3 @@ # better-sqlite3 [](https://github.com/JoshuaWise/better-sqlite3/actions/workflows/build.yml?query=branch%3Amaster) | ||
| > Requires a [currently supported Node.js](https://nodejs.org/en/about/previous-releases) version. Prebuilt binaries are available for [LTS versions](https://nodejs.org/en/about/previous-releases). If you have trouble installing, check the [troubleshooting guide](./docs/troubleshooting.md). | ||
| > Requires a [currently supported Node.js](https://nodejs.org/en/about/previous-releases) version. Prebuilt binaries are available for major platforms/architectures. If you have trouble installing, check the [troubleshooting guide](./docs/troubleshooting.md). | ||
@@ -38,0 +38,0 @@ ## Usage |
@@ -11,4 +11,3 @@ const napi_type_tag Backup::TYPE_TAG = RandomTypeTag(); | ||
| unlink(false) { | ||
| napi_status status = napi_type_tag_object(info.Env(), info.This(), &TYPE_TAG); | ||
| assert(status == napi_ok); ((void)status); | ||
| TYPE_TAG_CONSTRUCTOR(info); | ||
| JS_new(info); | ||
@@ -46,3 +45,3 @@ } | ||
| const Napi::CallbackInfo& pinfo = *addon->privileged_info; | ||
| Database* db = ::Unwrap<Database>(pinfo.This()); | ||
| UNWRAP_OR_RETURN(Database, db, pinfo.This()); | ||
| REQUIRE_DATABASE_OPEN(db->GetState()); | ||
@@ -93,3 +92,3 @@ REQUIRE_DATABASE_NOT_BUSY(db->GetState()); | ||
| NODE_METHOD(Backup::JS_transfer) { | ||
| Backup* backup = ::Unwrap<Backup>(info.This()); | ||
| UNWRAP_OR_RETURN(Backup, backup, info.This()); | ||
| REQUIRE_ARGUMENT_INT32(first, int pages); | ||
@@ -120,3 +119,3 @@ REQUIRE_DATABASE_OPEN(backup->db->GetState()); | ||
| NODE_METHOD(Backup::JS_close) { | ||
| Backup* backup = ::Unwrap<Backup>(info.This()); | ||
| UNWRAP_OR_RETURN(Backup, backup, info.This()); | ||
| assert(backup->db->GetState()->busy == false); | ||
@@ -123,0 +122,0 @@ if (backup->alive) backup->db->RemoveBackup(backup); |
+12
-13
@@ -26,4 +26,3 @@ // Node-API does not expose the engine's maximum Buffer/String sizes, so we | ||
| backups() { | ||
| napi_status status = napi_type_tag_object(info.Env(), info.This(), &TYPE_TAG); | ||
| assert(status == napi_ok); ((void)status); | ||
| TYPE_TAG_CONSTRUCTOR(info); | ||
| JS_new(info); | ||
@@ -219,3 +218,3 @@ } | ||
| NODE_METHOD(Database::JS_exec) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| REQUIRE_ARGUMENT_STRING(first, Napi::String source); | ||
@@ -280,3 +279,3 @@ REQUIRE_DATABASE_OPEN(db); | ||
| NODE_METHOD(Database::JS_serialize) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| REQUIRE_ARGUMENT_STRING(first, Napi::String attachedName); | ||
@@ -300,3 +299,3 @@ REQUIRE_DATABASE_OPEN(db); | ||
| NODE_METHOD(Database::JS_function) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| REQUIRE_ARGUMENT_FUNCTION(first, Napi::Function fn); | ||
@@ -326,3 +325,3 @@ REQUIRE_ARGUMENT_STRING(second, Napi::String nameString); | ||
| NODE_METHOD(Database::JS_aggregate) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| REQUIRE_ARGUMENT_ANY(first, Napi::Value start); | ||
@@ -357,3 +356,3 @@ REQUIRE_ARGUMENT_FUNCTION(second, Napi::Function step); | ||
| NODE_METHOD(Database::JS_table) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| REQUIRE_ARGUMENT_FUNCTION(first, Napi::Function factory); | ||
@@ -379,3 +378,3 @@ REQUIRE_ARGUMENT_STRING(second, Napi::String nameString); | ||
| NODE_METHOD(Database::JS_loadExtension) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| Napi::String entryPoint; | ||
@@ -407,3 +406,3 @@ REQUIRE_ARGUMENT_STRING(first, Napi::String filename); | ||
| NODE_METHOD(Database::JS_close) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| if (db->open) { | ||
@@ -419,3 +418,3 @@ REQUIRE_DATABASE_NOT_BUSY(db); | ||
| NODE_METHOD(Database::JS_defaultSafeIntegers) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| if (info.Length() == 0) db->safe_ints = true; | ||
@@ -427,3 +426,3 @@ else { REQUIRE_ARGUMENT_BOOLEAN(first, db->safe_ints); } | ||
| NODE_METHOD(Database::JS_unsafeMode) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| if (info.Length() == 0) db->unsafe_mode = true; | ||
@@ -436,3 +435,3 @@ else { REQUIRE_ARGUMENT_BOOLEAN(first, db->unsafe_mode); } | ||
| NODE_GETTER(Database::JS_open) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| return Napi::Boolean::New(info.Env(), db->open); | ||
@@ -442,4 +441,4 @@ } | ||
| NODE_GETTER(Database::JS_inTransaction) { | ||
| Database* db = ::Unwrap<Database>(info.This()); | ||
| UNWRAP_OR_RETURN(Database, db, info.This()); | ||
| return Napi::Boolean::New(info.Env(), db->open && !static_cast<bool>(sqlite3_get_autocommit(db->db_handle))); | ||
| } |
@@ -13,4 +13,3 @@ const napi_type_tag StatementIterator::TYPE_TAG = RandomTypeTag(); | ||
| logged(false) { | ||
| napi_status status = napi_type_tag_object(info.Env(), info.This(), &TYPE_TAG); | ||
| assert(status == napi_ok); ((void)status); | ||
| TYPE_TAG_CONSTRUCTOR(info); | ||
| JS_new(info); | ||
@@ -106,3 +105,3 @@ } | ||
| NODE_METHOD(StatementIterator::JS_next) { | ||
| StatementIterator* iter = ::Unwrap<StatementIterator>(info.This()); | ||
| UNWRAP_OR_RETURN(StatementIterator, iter, info.This()); | ||
| REQUIRE_DATABASE_NOT_BUSY(iter->db_state); | ||
@@ -114,3 +113,3 @@ if (iter->alive) return iter->Next(info.Env()); | ||
| NODE_METHOD(StatementIterator::JS_return) { | ||
| StatementIterator* iter = ::Unwrap<StatementIterator>(info.This()); | ||
| UNWRAP_OR_RETURN(StatementIterator, iter, info.This()); | ||
| REQUIRE_DATABASE_NOT_BUSY(iter->db_state); | ||
@@ -117,0 +116,0 @@ if (iter->alive) return iter->Return(info.Env()); |
@@ -48,5 +48,5 @@ class StatementIterator : public Napi::ObjectWrap<StatementIterator> { | ||
| napi_status status = napi_create_object(env, &record); | ||
| assert(status == napi_ok); | ||
| assert(status == napi_ok || status == napi_cannot_run_js); | ||
| status = napi_define_properties(env, record, 2, properties); | ||
| assert(status == napi_ok); ((void)status); | ||
| assert(status == napi_ok || status == napi_cannot_run_js); ((void)status); | ||
| return Napi::Object(env, record); | ||
@@ -53,0 +53,0 @@ } |
@@ -15,4 +15,3 @@ const napi_type_tag Statement::TYPE_TAG = RandomTypeTag(); | ||
| returns_data(false) { | ||
| napi_status status = napi_type_tag_object(info.Env(), info.This(), &TYPE_TAG); | ||
| assert(status == napi_ok); ((void)status); | ||
| TYPE_TAG_CONSTRUCTOR(info); | ||
| JS_new(info); | ||
@@ -86,3 +85,3 @@ } | ||
| const Napi::CallbackInfo& pinfo = *addon->privileged_info; | ||
| Database* db = ::Unwrap<Database>(pinfo.This()); | ||
| UNWRAP_OR_RETURN(Database, db, pinfo.This()); | ||
| REQUIRE_DATABASE_OPEN(db->GetState()); | ||
@@ -192,5 +191,5 @@ REQUIRE_DATABASE_NOT_BUSY(db->GetState()); | ||
| napi_status status = napi_create_object(env, &result); | ||
| assert(status == napi_ok); | ||
| assert(status == napi_ok || status == napi_cannot_run_js); | ||
| status = napi_define_properties(env, result, 2, properties); | ||
| assert(status == napi_ok); ((void)status); | ||
| assert(status == napi_ok || status == napi_cannot_run_js); ((void)status); | ||
| STATEMENT_RETURN(Napi::Object(env, result)); | ||
@@ -271,3 +270,3 @@ } | ||
| NODE_METHOD(Statement::JS_bind) { | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); | ||
| if (stmt->bound) return ThrowTypeError(info.Env(), "The bind() method can only be invoked once per statement object"); | ||
@@ -283,3 +282,3 @@ REQUIRE_DATABASE_OPEN(stmt->db->GetState()); | ||
| NODE_METHOD(Statement::JS_pluck) { | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); | ||
| if (!stmt->returns_data) return ThrowTypeError(info.Env(), "The pluck() method is only for statements that return data"); | ||
@@ -295,3 +294,3 @@ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState()); | ||
| NODE_METHOD(Statement::JS_expand) { | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); | ||
| if (!stmt->returns_data) return ThrowTypeError(info.Env(), "The expand() method is only for statements that return data"); | ||
@@ -307,3 +306,3 @@ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState()); | ||
| NODE_METHOD(Statement::JS_raw) { | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); | ||
| if (!stmt->returns_data) return ThrowTypeError(info.Env(), "The raw() method is only for statements that return data"); | ||
@@ -319,3 +318,3 @@ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState()); | ||
| NODE_METHOD(Statement::JS_safeIntegers) { | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); | ||
| REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState()); | ||
@@ -329,3 +328,3 @@ REQUIRE_STATEMENT_NOT_LOCKED(stmt); | ||
| NODE_METHOD(Statement::JS_columns) { | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); | ||
| if (!stmt->returns_data) return ThrowTypeError(info.Env(), "The columns() method is only for statements that return data"); | ||
@@ -372,3 +371,3 @@ REQUIRE_DATABASE_OPEN(stmt->db->GetState()); | ||
| NODE_METHOD(Statement::JS_toString) { | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); | ||
| Addon* addon = stmt->db->GetAddon(); | ||
@@ -389,4 +388,4 @@ | ||
| NODE_GETTER(Statement::JS_busy) { | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); | ||
| return Napi::Boolean::New(info.Env(), stmt->alive && stmt->locked); | ||
| } |
@@ -93,3 +93,5 @@ inline Napi::String StringFromUtf8(Napi::Env env, const char* data, int length) { | ||
| // value produced by our own code), because napi_unwrap does not check the | ||
| // object's type. | ||
| // object's type. Returns NULL if the environment can no longer run JavaScript | ||
| // (e.g., worker.terminate()), so callers should use UNWRAP_OR_RETURN, which | ||
| // checks for that case. | ||
| template <typename T> inline T* Unwrap(Napi::Value value) { | ||
@@ -173,3 +175,3 @@ return T::Unwrap(value.As<Napi::Object>()); | ||
| napi_status status = napi_define_properties(obj.Env(), obj, 1, &desc); | ||
| assert(status == napi_ok); ((void)status); | ||
| assert(status == napi_ok || status == napi_cannot_run_js); ((void)status); | ||
| } | ||
@@ -176,0 +178,0 @@ |
+14
-0
@@ -11,2 +11,16 @@ #define NODE_ARGUMENTS const Napi::CallbackInfo& | ||
| // Type-tag an object, but bail if the thread is terminating, to avoid | ||
| // undesirable side-effects in the subsequent JS_new call (e.g, sqlite3_open()). | ||
| #define TYPE_TAG_CONSTRUCTOR(info) \ | ||
| napi_status status = \ | ||
| napi_type_tag_object((info).Env(), (info).This(), &TYPE_TAG); \ | ||
| assert(status == napi_ok || status == napi_cannot_run_js); \ | ||
| if (status != napi_ok) return | ||
| // Unwrap a native-backed object (see ::Unwrap in helpers.cpp), but bail if the | ||
| // the unwrap fails (which should only happen if the thread is terminating). | ||
| #define UNWRAP_OR_RETURN(T, var, value) \ | ||
| T* var = ::Unwrap<T>(value); \ | ||
| if (var == NULL) return info.Env().Undefined() | ||
| #define REQUIRE_ARGUMENT_ANY(at, var) \ | ||
@@ -13,0 +27,0 @@ if (info.Length() <= (at())) \ |
@@ -19,3 +19,3 @@ #define STATEMENT_BIND(handle) \ | ||
| #define STATEMENT_START_LOGIC(RETURNS_DATA_CHECK, MUTATE_CHECK) \ | ||
| Statement* stmt = ::Unwrap<Statement>(info.This()); \ | ||
| UNWRAP_OR_RETURN(Statement, stmt, info.This()); \ | ||
| RETURNS_DATA_CHECK(); \ | ||
@@ -22,0 +22,0 @@ sqlite3_stmt* handle = stmt->handle; \ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
27353961
0.16%683
0.89%