Skip to content

Commit 62ba619

Browse files
committed
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: #58378 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent dd205c9 commit 62ba619

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
@@ -1005,6 +1005,14 @@ void DatabaseSync::Close(const FunctionCallbackInfo<Value>& args) {
10051005
db->connection_ = nullptr;
10061006
}
10071007

1008+
void DatabaseSync::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
1009+
v8::TryCatch try_catch(args.GetIsolate());
1010+
Close(args);
1011+
if (try_catch.HasCaught()) {
1012+
CHECK(try_catch.CanContinue());
1013+
}
1014+
}
1015+
10081016
void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
10091017
DatabaseSync* db;
10101018
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
@@ -2577,6 +2585,7 @@ Local<FunctionTemplate> Session::GetConstructorTemplate(Environment* env) {
25772585
SetProtoMethod(
25782586
isolate, tmpl, "patchset", Session::Changeset<sqlite3session_patchset>);
25792587
SetProtoMethod(isolate, tmpl, "close", Session::Close);
2588+
SetProtoDispose(isolate, tmpl, Session::Dispose);
25802589
env->set_sqlite_session_constructor_template(tmpl);
25812590
}
25822591
return tmpl;
@@ -2621,6 +2630,14 @@ void Session::Close(const FunctionCallbackInfo<Value>& args) {
26212630
session->Delete();
26222631
}
26232632

2633+
void Session::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
2634+
v8::TryCatch try_catch(args.GetIsolate());
2635+
Close(args);
2636+
if (try_catch.HasCaught()) {
2637+
CHECK(try_catch.CanContinue());
2638+
}
2639+
}
2640+
26242641
void Session::Delete() {
26252642
if (!database_ || !database_->connection_ || session_ == nullptr) return;
26262643
sqlite3session_delete(session_);
@@ -2656,6 +2673,7 @@ static void Initialize(Local<Object> target,
26562673

26572674
SetProtoMethod(isolate, db_tmpl, "open", DatabaseSync::Open);
26582675
SetProtoMethod(isolate, db_tmpl, "close", DatabaseSync::Close);
2676+
SetProtoDispose(isolate, db_tmpl, DatabaseSync::Dispose);
26592677
SetProtoMethod(isolate, db_tmpl, "prepare", DatabaseSync::Prepare);
26602678
SetProtoMethod(isolate, db_tmpl, "exec", DatabaseSync::Exec);
26612679
SetProtoMethod(isolate, db_tmpl, "function", DatabaseSync::CustomFunction);
@@ -2686,6 +2704,8 @@ static void Initialize(Local<Object> target,
26862704
target,
26872705
"StatementSync",
26882706
StatementSync::GetConstructorTemplate(env));
2707+
SetConstructorFunction(
2708+
context, target, "Session", Session::GetConstructorTemplate(env));
26892709

26902710
target->Set(context, env->constants_string(), constants).Check();
26912711

src/node_sqlite.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class DatabaseSync : public BaseObject {
6464
static void IsTransactionGetter(
6565
const v8::FunctionCallbackInfo<v8::Value>& args);
6666
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
67+
static void Dispose(const v8::FunctionCallbackInfo<v8::Value>& args);
6768
static void Prepare(const v8::FunctionCallbackInfo<v8::Value>& args);
6869
static void Exec(const v8::FunctionCallbackInfo<v8::Value>& args);
6970
static void Location(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -194,6 +195,7 @@ class Session : public BaseObject {
194195
template <Sqlite3ChangesetGenFunc sqliteChangesetFunc>
195196
static void Changeset(const v8::FunctionCallbackInfo<v8::Value>& args);
196197
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
198+
static void Dispose(const v8::FunctionCallbackInfo<v8::Value>& args);
197199
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
198200
Environment* env);
199201
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
@@ -926,6 +926,16 @@ void SetMethodNoSideEffect(v8::Isolate* isolate,
926926
const std::string_view name,
927927
v8::FunctionCallback callback);
928928

929+
// Set the Symbol.dispose method on the prototype of the class.
930+
void SetProtoDispose(v8::Isolate* isolate,
931+
v8::Local<v8::FunctionTemplate> that,
932+
v8::FunctionCallback callback);
933+
934+
// Set the Symbol.asyncDispose method on the prototype of the class.
935+
void SetProtoAsyncDispose(v8::Isolate* isolate,
936+
v8::Local<v8::FunctionTemplate> that,
937+
v8::FunctionCallback callback);
938+
929939
enum class SetConstructorFunctionFlag {
930940
NONE,
931941
SET_CLASS_NAME,

test/parallel/test-sqlite-session.js

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

0 commit comments

Comments
 (0)