| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d7d4f0e commit c2a5251
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2124,7 +2124,7 @@ void DatabaseSync::CreateSession(const FunctionCallbackInfo<Value>& args) { | |||
| 2124 | 2124 | CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void()); | |
| 2125 | 2125 | ||
| 2126 | 2126 | BaseObjectPtr<Session> session = | |
| 2127 | - Session::Create(env, BaseObjectWeakPtr<DatabaseSync>(db), pSession); | ||
| 2127 | + Session::Create(env, BaseObjectPtr<DatabaseSync>(db), pSession); | ||
| 2128 | 2128 | args.GetReturnValue().Set(session->object()); | |
| 2129 | 2129 | } | |
| 2130 | 2130 | ||
@@ -3803,7 +3803,7 @@ void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) { | |||
| 3803 | 3803 | ||
| 3804 | 3804 | Session::Session(Environment* env, | |
| 3805 | 3805 | Local<Object> object, | |
| 3806 | - BaseObjectWeakPtr<DatabaseSync> database, | ||
| 3806 | + BaseObjectPtr<DatabaseSync> database, | ||
| 3807 | 3807 | sqlite3_session* session) | |
| 3808 | 3808 | : BaseObject(env, object), | |
| 3809 | 3809 | session_(session), | |
@@ -3816,7 +3816,7 @@ Session::~Session() { | |||
| 3816 | 3816 | } | |
| 3817 | 3817 | ||
| 3818 | 3818 | BaseObjectPtr<Session> Session::Create(Environment* env, | |
| 3819 | - BaseObjectWeakPtr<DatabaseSync> database, | ||
| 3819 | + BaseObjectPtr<DatabaseSync> database, | ||
| 3820 | 3820 | sqlite3_session* session) { | |
| 3821 | 3821 | Local<Object> obj; | |
| 3822 | 3822 | if (!GetConstructorTemplate(env) | |
@@ -3850,7 +3850,9 @@ Local<FunctionTemplate> Session::GetConstructorTemplate(Environment* env) { | |||
| 3850 | 3850 | return tmpl; | |
| 3851 | 3851 | } | |
| 3852 | 3852 | ||
| 3853 | - void Session::MemoryInfo(MemoryTracker* tracker) const {} | ||
| 3853 | + void Session::MemoryInfo(MemoryTracker* tracker) const { | ||
| 3854 | + tracker->TrackField("database", database_); | ||
| 3855 | + } | ||
| 3854 | 3856 | ||
| 3855 | 3857 | template <Sqlite3ChangesetGenFunc sqliteChangesetFunc> | |
| 3856 | 3858 | void Session::Changeset(const FunctionCallbackInfo<Value>& args) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -339,7 +339,7 @@ class Session : public BaseObject { | |||
| 339 | 339 | public: | |
| 340 | 340 | Session(Environment* env, | |
| 341 | 341 | v8::Local<v8::Object> object, | |
| 342 | - BaseObjectWeakPtr<DatabaseSync> database, | ||
| 342 | + BaseObjectPtr<DatabaseSync> database, | ||
| 343 | 343 | sqlite3_session* session); | |
| 344 | 344 | ~Session() override; | |
| 345 | 345 | template <Sqlite3ChangesetGenFunc sqliteChangesetFunc> | |
@@ -349,7 +349,7 @@ class Session : public BaseObject { | |||
| 349 | 349 | static v8::Local<v8::FunctionTemplate> GetConstructorTemplate( | |
| 350 | 350 | Environment* env); | |
| 351 | 351 | static BaseObjectPtr<Session> Create(Environment* env, | |
| 352 | - BaseObjectWeakPtr<DatabaseSync> database, | ||
| 352 | + BaseObjectPtr<DatabaseSync> database, | ||
| 353 | 353 | sqlite3_session* session); | |
| 354 | 354 | ||
| 355 | 355 | void MemoryInfo(MemoryTracker* tracker) const override; | |
@@ -359,7 +359,7 @@ class Session : public BaseObject { | |||
| 359 | 359 | private: | |
| 360 | 360 | void Delete(); | |
| 361 | 361 | sqlite3_session* session_; | |
| 362 | - BaseObjectWeakPtr<DatabaseSync> database_; // The Parent Database | ||
| 362 | + BaseObjectPtr<DatabaseSync> database_; // The Parent Database | ||
| 363 | 363 | }; | |
| 364 | 364 | ||
| 365 | 365 | class SQLTagStore : public BaseObject { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,4 @@ | |||
| 1 | - // Flags: --experimental-sqlite | ||
| 1 | + // Flags: --expose-gc --experimental-sqlite | ||
| 2 | 2 | 'use strict'; | |
| 3 | 3 | const { skipIfSQLiteMissing } = require('../common'); | |
| 4 | 4 | skipIfSQLiteMissing(); | |
@@ -589,6 +589,36 @@ test('session.close() - closing twice', (t) => { | |||
| 589 | 589 | }); | |
| 590 | 590 | }); | |
| 591 | 591 | ||
| 592 | + test('session - keeps its database alive after the db handle is dropped', async (t) => { | ||
| 593 | + const { gcUntil, onGC } = require('../common/gc'); | ||
| 594 | + | ||
| 595 | + // The DatabaseSync handle is created in a nested scope and never referenced | ||
| 596 | + // again, so the returned session is the only thing keeping it reachable. | ||
| 597 | + let dbCollected = false; | ||
| 598 | + const session = (() => { | ||
| 599 | + const database = new DatabaseSync(':memory:'); | ||
| 600 | + database.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)'); | ||
| 601 | + onGC(database, { ongc: () => { dbCollected = true; } }); | ||
| 602 | + const s = database.createSession(); | ||
| 603 | + database.exec("INSERT INTO data VALUES (1, 'hello')"); | ||
| 604 | + return s; | ||
| 605 | + })(); | ||
| 606 | + | ||
| 607 | + // The session must keep the database alive across GC. Previously it held | ||
| 608 | + // only a weak reference, so the database could be collected and using the | ||
| 609 | + // session afterwards dereferenced a dangling pointer and crashed. | ||
| 610 | + await gcUntil('database is collected', () => dbCollected, 5).then( | ||
| 611 | + () => { throw new Error('session did not keep its database alive'); }, | ||
| 612 | + () => {}, // Expected: the database is never collected, so gcUntil rejects. | ||
| 613 | + ); | ||
| 614 | + t.assert.strictEqual(dbCollected, false); | ||
| 615 | + | ||
| 616 | + // The database is still open and usable through the still-alive session. | ||
| 617 | + const changeset = session.changeset(); | ||
| 618 | + t.assert.ok(changeset.byteLength > 0); | ||
| 619 | + session.close(); | ||
| 620 | + }); | ||
| 621 | + | ||
| 592 | 622 | test('session supports ERM', (t) => { | |
| 593 | 623 | const database = new DatabaseSync(':memory:'); | |
| 594 | 624 | let afterDisposeSession; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments