Skip to content

Commit f4140ec

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
1 parent 73e7bd1 commit f4140ec

File tree

6 files changed

+78
-14
lines changed

6 files changed

+78
-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
@@ -1000,6 +1000,14 @@ void DatabaseSync::Close(const FunctionCallbackInfo<Value>& args) {
10001000
db->connection_ = nullptr;
10011001
}
10021002

1003+
void DatabaseSync::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
1004+
v8::TryCatch try_catch(args.GetIsolate());
1005+
Close(args);
1006+
if (try_catch.HasCaught()) {
1007+
CHECK(try_catch.CanContinue());
1008+
}
1009+
}
1010+
10031011
void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
10041012
DatabaseSync* db;
10051013
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
@@ -2572,6 +2580,7 @@ Local<FunctionTemplate> Session::GetConstructorTemplate(Environment* env) {
25722580
SetProtoMethod(
25732581
isolate, tmpl, "patchset", Session::Changeset<sqlite3session_patchset>);
25742582
SetProtoMethod(isolate, tmpl, "close", Session::Close);
2583+
SetProtoDispose(isolate, tmpl, Session::Dispose);
25752584
env->set_sqlite_session_constructor_template(tmpl);
25762585
}
25772586
return tmpl;
@@ -2616,6 +2625,14 @@ void Session::Close(const FunctionCallbackInfo<Value>& args) {
26162625
session->Delete();
26172626
}
26182627

2628+
void Session::Dispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
2629+
v8::TryCatch try_catch(args.GetIsolate());
2630+
Close(args);
2631+
if (try_catch.HasCaught()) {
2632+
CHECK(try_catch.CanContinue());
2633+
}
2634+
}
2635+
26192636
void Session::Delete() {
26202637
if (!database_ || !database_->connection_ || session_ == nullptr) return;
26212638
sqlite3session_delete(session_);
@@ -2651,6 +2668,7 @@ static void Initialize(Local<Object> target,
26512668

26522669
SetProtoMethod(isolate, db_tmpl, "open", DatabaseSync::Open);
26532670
SetProtoMethod(isolate, db_tmpl, "close", DatabaseSync::Close);
2671+
SetProtoDispose(isolate, db_tmpl, DatabaseSync::Dispose);
26542672
SetProtoMethod(isolate, db_tmpl, "prepare", DatabaseSync::Prepare);
26552673
SetProtoMethod(isolate, db_tmpl, "exec", DatabaseSync::Exec);
26562674
SetProtoMethod(isolate, db_tmpl, "function", DatabaseSync::CustomFunction);
@@ -2681,6 +2699,8 @@ static void Initialize(Local<Object> target,
26812699
target,
26822700
"StatementSync",
26832701
StatementSync::GetConstructorTemplate(env));
2702+
SetConstructorFunction(
2703+
context, target, "Session", Session::GetConstructorTemplate(env));
26842704

26852705
target->Set(context, env->constants_string(), constants).Check();
26862706

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: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,36 @@ 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+
// kInternalized strings are created in the old space.
612+
const v8::NewStringType type = v8::NewStringType::kInternalized;
613+
that->PrototypeTemplate()->Set(v8::Symbol::GetDispose(isolate), t);
614+
}
615+
616+
void SetProtoAsyncDispose(v8::Isolate* isolate,
617+
v8::Local<v8::FunctionTemplate> that,
618+
v8::FunctionCallback callback) {
619+
Local<v8::Signature> signature = v8::Signature::New(isolate, that);
620+
Local<v8::FunctionTemplate> t =
621+
NewFunctionTemplate(isolate,
622+
callback,
623+
signature,
624+
v8::ConstructorBehavior::kThrow,
625+
v8::SideEffectType::kHasSideEffect);
626+
// kInternalized strings are created in the old space.
627+
const v8::NewStringType type = v8::NewStringType::kInternalized;
628+
that->PrototypeTemplate()->Set(v8::Symbol::GetAsyncDispose(isolate), t);
629+
}
630+
601631
void SetProtoMethod(v8::Isolate* isolate,
602632
Local<v8::FunctionTemplate> that,
603633
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)