sqlite: cleanup ERM support and export Session class
Update sqlite Session to support Symbol.dispose and move the definition of the dispose methods to c++ to close the open TODO PR-URL: https://github.com/nodejs/node/pull/58378 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
parent
dd205c9831
commit
62ba6196d4
@ -1,19 +1,6 @@
|
||||
'use strict';
|
||||
const {
|
||||
SymbolDispose,
|
||||
} = primordials;
|
||||
const { emitExperimentalWarning } = require('internal/util');
|
||||
const binding = internalBinding('sqlite');
|
||||
|
||||
emitExperimentalWarning('SQLite');
|
||||
|
||||
// TODO(cjihrig): Move this to C++ once Symbol.dispose reaches Stage 4.
|
||||
binding.DatabaseSync.prototype[SymbolDispose] = function() {
|
||||
try {
|
||||
this.close();
|
||||
} catch {
|
||||
// Ignore errors.
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = binding;
|
||||
module.exports = internalBinding('sqlite');
|
||||
|
@ -1005,6 +1005,14 @@ void DatabaseSync::Close(const FunctionCallbackInfo<Value>& args) {
|
||||
db->connection_ = nullptr;
|
||||
}
|
||||
|
||||
void DatabaseSync::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
v8::TryCatch try_catch(args.GetIsolate());
|
||||
Close(args);
|
||||
if (try_catch.HasCaught()) {
|
||||
CHECK(try_catch.CanContinue());
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
|
||||
DatabaseSync* db;
|
||||
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
||||
@ -2577,6 +2585,7 @@ Local<FunctionTemplate> Session::GetConstructorTemplate(Environment* env) {
|
||||
SetProtoMethod(
|
||||
isolate, tmpl, "patchset", Session::Changeset<sqlite3session_patchset>);
|
||||
SetProtoMethod(isolate, tmpl, "close", Session::Close);
|
||||
SetProtoDispose(isolate, tmpl, Session::Dispose);
|
||||
env->set_sqlite_session_constructor_template(tmpl);
|
||||
}
|
||||
return tmpl;
|
||||
@ -2621,6 +2630,14 @@ void Session::Close(const FunctionCallbackInfo<Value>& args) {
|
||||
session->Delete();
|
||||
}
|
||||
|
||||
void Session::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
v8::TryCatch try_catch(args.GetIsolate());
|
||||
Close(args);
|
||||
if (try_catch.HasCaught()) {
|
||||
CHECK(try_catch.CanContinue());
|
||||
}
|
||||
}
|
||||
|
||||
void Session::Delete() {
|
||||
if (!database_ || !database_->connection_ || session_ == nullptr) return;
|
||||
sqlite3session_delete(session_);
|
||||
@ -2656,6 +2673,7 @@ static void Initialize(Local<Object> target,
|
||||
|
||||
SetProtoMethod(isolate, db_tmpl, "open", DatabaseSync::Open);
|
||||
SetProtoMethod(isolate, db_tmpl, "close", DatabaseSync::Close);
|
||||
SetProtoDispose(isolate, db_tmpl, DatabaseSync::Dispose);
|
||||
SetProtoMethod(isolate, db_tmpl, "prepare", DatabaseSync::Prepare);
|
||||
SetProtoMethod(isolate, db_tmpl, "exec", DatabaseSync::Exec);
|
||||
SetProtoMethod(isolate, db_tmpl, "function", DatabaseSync::CustomFunction);
|
||||
@ -2686,6 +2704,8 @@ static void Initialize(Local<Object> target,
|
||||
target,
|
||||
"StatementSync",
|
||||
StatementSync::GetConstructorTemplate(env));
|
||||
SetConstructorFunction(
|
||||
context, target, "Session", Session::GetConstructorTemplate(env));
|
||||
|
||||
target->Set(context, env->constants_string(), constants).Check();
|
||||
|
||||
|
@ -64,6 +64,7 @@ class DatabaseSync : public BaseObject {
|
||||
static void IsTransactionGetter(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Dispose(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Prepare(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Exec(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Location(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
@ -194,6 +195,7 @@ class Session : public BaseObject {
|
||||
template <Sqlite3ChangesetGenFunc sqliteChangesetFunc>
|
||||
static void Changeset(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Dispose(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
|
||||
Environment* env);
|
||||
static BaseObjectPtr<Session> Create(Environment* env,
|
||||
|
26
src/util.cc
26
src/util.cc
@ -598,6 +598,32 @@ void SetMethodNoSideEffect(Isolate* isolate,
|
||||
that->Set(name_string, t);
|
||||
}
|
||||
|
||||
void SetProtoDispose(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> that,
|
||||
v8::FunctionCallback callback) {
|
||||
Local<v8::Signature> signature = v8::Signature::New(isolate, that);
|
||||
Local<v8::FunctionTemplate> t =
|
||||
NewFunctionTemplate(isolate,
|
||||
callback,
|
||||
signature,
|
||||
v8::ConstructorBehavior::kThrow,
|
||||
v8::SideEffectType::kHasSideEffect);
|
||||
that->PrototypeTemplate()->Set(v8::Symbol::GetDispose(isolate), t);
|
||||
}
|
||||
|
||||
void SetProtoAsyncDispose(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> that,
|
||||
v8::FunctionCallback callback) {
|
||||
Local<v8::Signature> signature = v8::Signature::New(isolate, that);
|
||||
Local<v8::FunctionTemplate> t =
|
||||
NewFunctionTemplate(isolate,
|
||||
callback,
|
||||
signature,
|
||||
v8::ConstructorBehavior::kThrow,
|
||||
v8::SideEffectType::kHasSideEffect);
|
||||
that->PrototypeTemplate()->Set(v8::Symbol::GetAsyncDispose(isolate), t);
|
||||
}
|
||||
|
||||
void SetProtoMethod(v8::Isolate* isolate,
|
||||
Local<v8::FunctionTemplate> that,
|
||||
const std::string_view name,
|
||||
|
10
src/util.h
10
src/util.h
@ -926,6 +926,16 @@ void SetMethodNoSideEffect(v8::Isolate* isolate,
|
||||
const std::string_view name,
|
||||
v8::FunctionCallback callback);
|
||||
|
||||
// Set the Symbol.dispose method on the prototype of the class.
|
||||
void SetProtoDispose(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> that,
|
||||
v8::FunctionCallback callback);
|
||||
|
||||
// Set the Symbol.asyncDispose method on the prototype of the class.
|
||||
void SetProtoAsyncDispose(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> that,
|
||||
v8::FunctionCallback callback);
|
||||
|
||||
enum class SetConstructorFunctionFlag {
|
||||
NONE,
|
||||
SET_CLASS_NAME,
|
||||
|
@ -539,3 +539,18 @@ test('session.close() - closing twice', (t) => {
|
||||
message: 'session is not open'
|
||||
});
|
||||
});
|
||||
|
||||
test('session supports ERM', (t) => {
|
||||
const database = new DatabaseSync(':memory:');
|
||||
let afterDisposeSession;
|
||||
{
|
||||
using session = database.createSession();
|
||||
afterDisposeSession = session;
|
||||
const changeset = session.changeset();
|
||||
t.assert.ok(changeset instanceof Uint8Array);
|
||||
t.assert.strictEqual(changeset.length, 0);
|
||||
}
|
||||
t.assert.throws(() => afterDisposeSession.changeset(), {
|
||||
message: /session is not open/,
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user