Skip to content

Commit 7af2013

Browse files
jasnellRenegade334
authored andcommitted
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: nodejs#58378 Backport-PR-URL: https://github.com/nodejs/node/pull/00000 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent 634a889 commit 7af2013

File tree

6 files changed

+74
-14
lines changed

6 files changed

+74
-14
lines changed

lib/sqlite.js

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,6 @@
11
'use strict';
2-
const {
3-
SymbolDispose,
4-
} = primordials;
52
const { emitExperimentalWarning } = require('internal/util');
6-
const binding = internalBinding('sqlite');
73

84
emitExperimentalWarning('SQLite');
95

10-
// TODO(cjihrig): Move this to C++ once Symbol.dispose reaches Stage 4.
11-
binding.DatabaseSync.prototype[SymbolDispose] = function() {
12-
try {
13-
this.close();
14-
} catch {
15-
// Ignore errors.
16-
}
17-
};
18-
19-
module.exports = binding;
6+
module.exports = internalBinding('sqlite');

src/node_sqlite.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,14 @@ void DatabaseSync::Close(const FunctionCallbackInfo<Value>& args) {
10801080
db->connection_ = nullptr;
10811081
}
10821082

1083+
void DatabaseSync::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
1084+
v8::TryCatch try_catch(args.GetIsolate());
1085+
Close(args);
1086+
if (try_catch.HasCaught()) {
1087+
CHECK(try_catch.CanContinue());
1088+
}
1089+
}
1090+
10831091
void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
10841092
DatabaseSync* db;
10851093
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
@@ -2629,6 +2637,7 @@ Local<FunctionTemplate> Session::GetConstructorTemplate(Environment* env) {
26292637
SetProtoMethod(
26302638
isolate, tmpl, "patchset", Session::Changeset<sqlite3session_patchset>);
26312639
SetProtoMethod(isolate, tmpl, "close", Session::Close);
2640+
SetProtoDispose(isolate, tmpl, Session::Dispose);
26322641
env->set_sqlite_session_constructor_template(tmpl);
26332642
}
26342643
return tmpl;
@@ -2673,6 +2682,14 @@ void Session::Close(const FunctionCallbackInfo<Value>& args) {
26732682
session->Delete();
26742683
}
26752684

2685+
void Session::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
2686+
v8::TryCatch try_catch(args.GetIsolate());
2687+
Close(args);
2688+
if (try_catch.HasCaught()) {
2689+
CHECK(try_catch.CanContinue());
2690+
}
2691+
}
2692+
26762693
void Session::Delete() {
26772694
if (!database_ || !database_->connection_ || session_ == nullptr) return;
26782695
sqlite3session_delete(session_);
@@ -2708,6 +2725,7 @@ static void Initialize(Local<Object> target,
27082725

27092726
SetProtoMethod(isolate, db_tmpl, "open", DatabaseSync::Open);
27102727
SetProtoMethod(isolate, db_tmpl, "close", DatabaseSync::Close);
2728+
SetProtoDispose(isolate, db_tmpl, DatabaseSync::Dispose);
27112729
SetProtoMethod(isolate, db_tmpl, "prepare", DatabaseSync::Prepare);
27122730
SetProtoMethod(isolate, db_tmpl, "exec", DatabaseSync::Exec);
27132731
SetProtoMethod(isolate, db_tmpl, "function", DatabaseSync::CustomFunction);
@@ -2745,6 +2763,8 @@ static void Initialize(Local<Object> target,
27452763
target,
27462764
"StatementSync",
27472765
StatementSync::GetConstructorTemplate(env));
2766+
SetConstructorFunction(
2767+
context, target, "Session", Session::GetConstructorTemplate(env));
27482768

27492769
target->Set(context, env->constants_string(), constants).Check();
27502770

src/node_sqlite.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class DatabaseSync : public BaseObject {
9292
static void IsTransactionGetter(
9393
const v8::FunctionCallbackInfo<v8::Value>& args);
9494
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
95+
static void Dispose(const v8::FunctionCallbackInfo<v8::Value>& args);
9596
static void Prepare(const v8::FunctionCallbackInfo<v8::Value>& args);
9697
static void Exec(const v8::FunctionCallbackInfo<v8::Value>& args);
9798
static void Location(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -230,6 +231,7 @@ class Session : public BaseObject {
230231
template <Sqlite3ChangesetGenFunc sqliteChangesetFunc>
231232
static void Changeset(const v8::FunctionCallbackInfo<v8::Value>& args);
232233
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
234+
static void Dispose(const v8::FunctionCallbackInfo<v8::Value>& args);
233235
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
234236
Environment* env);
235237
static BaseObjectPtr<Session> Create(Environment* env,

src/util.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,32 @@ void SetMethodNoSideEffect(Isolate* isolate,
598598
that->Set(name_string, t);
599599
}
600600

601+
void SetProtoDispose(v8::Isolate* isolate,
602+
v8::Local<v8::FunctionTemplate> that,
603+
v8::FunctionCallback callback) {
604+
Local<v8::Signature> signature = v8::Signature::New(isolate, that);
605+
Local<v8::FunctionTemplate> t =
606+
NewFunctionTemplate(isolate,
607+
callback,
608+
signature,
609+
v8::ConstructorBehavior::kThrow,
610+
v8::SideEffectType::kHasSideEffect);
611+
that->PrototypeTemplate()->Set(v8::Symbol::GetDispose(isolate), t);
612+
}
613+
614+
void SetProtoAsyncDispose(v8::Isolate* isolate,
615+
v8::Local<v8::FunctionTemplate> that,
616+
v8::FunctionCallback callback) {
617+
Local<v8::Signature> signature = v8::Signature::New(isolate, that);
618+
Local<v8::FunctionTemplate> t =
619+
NewFunctionTemplate(isolate,
620+
callback,
621+
signature,
622+
v8::ConstructorBehavior::kThrow,
623+
v8::SideEffectType::kHasSideEffect);
624+
that->PrototypeTemplate()->Set(v8::Symbol::GetAsyncDispose(isolate), t);
625+
}
626+
601627
void SetProtoMethod(v8::Isolate* isolate,
602628
Local<v8::FunctionTemplate> that,
603629
const std::string_view name,

src/util.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,16 @@ void SetMethodNoSideEffect(v8::Isolate* isolate,
936936
const std::string_view name,
937937
v8::FunctionCallback callback);
938938

939+
// Set the Symbol.dispose method on the prototype of the class.
940+
void SetProtoDispose(v8::Isolate* isolate,
941+
v8::Local<v8::FunctionTemplate> that,
942+
v8::FunctionCallback callback);
943+
944+
// Set the Symbol.asyncDispose method on the prototype of the class.
945+
void SetProtoAsyncDispose(v8::Isolate* isolate,
946+
v8::Local<v8::FunctionTemplate> that,
947+
v8::FunctionCallback callback);
948+
939949
enum class SetConstructorFunctionFlag {
940950
NONE,
941951
SET_CLASS_NAME,

test/parallel/test-sqlite-session.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,3 +540,18 @@ test('session.close() - closing twice', (t) => {
540540
message: 'session is not open'
541541
});
542542
});
543+
544+
test('session supports ERM', (t) => {
545+
const database = new DatabaseSync(':memory:');
546+
let afterDisposeSession;
547+
{
548+
using session = database.createSession();
549+
afterDisposeSession = session;
550+
const changeset = session.changeset();
551+
t.assert.ok(changeset instanceof Uint8Array);
552+
t.assert.strictEqual(changeset.length, 0);
553+
}
554+
t.assert.throws(() => afterDisposeSession.changeset(), {
555+
message: /session is not open/,
556+
});
557+
});

0 commit comments

Comments
 (0)