@@ -162,24 +162,57 @@ export interface IdbDatabaseDebugIdPair {
162162
163163class SimpleDbStateNew {
164164 readonly name = 'new' as const ;
165+
166+ constructor (
167+ readonly databaseDeletedListener : DatabaseDeletedListener | null
168+ ) { }
169+
170+ withDatabaseDeletedListener (
171+ databaseDeletedListener : DatabaseDeletedListener
172+ ) : SimpleDbStateNew {
173+ return new SimpleDbStateNew ( databaseDeletedListener ) ;
174+ }
165175}
166176
167177class SimpleDbStateOpening {
168178 readonly name = 'opening' as const ;
169179
170- constructor ( readonly promise : Promise < unknown > ) { }
180+ constructor (
181+ readonly promise : Promise < unknown > ,
182+ readonly databaseDeletedListener : DatabaseDeletedListener | null
183+ ) { }
184+
185+ withDatabaseDeletedListener (
186+ databaseDeletedListener : DatabaseDeletedListener
187+ ) : SimpleDbStateOpening {
188+ return new SimpleDbStateOpening ( this . promise , databaseDeletedListener ) ;
189+ }
171190}
172191
173192class SimpleDbStateOpened {
174193 readonly name = 'opened' as const ;
175194
176- constructor ( readonly db : IdbDatabaseDebugIdPair ) { }
195+ constructor (
196+ readonly db : IdbDatabaseDebugIdPair ,
197+ readonly databaseDeletedListener : DatabaseDeletedListener | null
198+ ) { }
199+
200+ withDatabaseDeletedListener (
201+ databaseDeletedListener : DatabaseDeletedListener
202+ ) : SimpleDbStateOpened {
203+ return new SimpleDbStateOpened ( this . db , databaseDeletedListener ) ;
204+ }
205+ }
206+
207+ class SimpleDbStateClosed {
208+ readonly name = 'closed' as const ;
177209}
178210
179211type SimpleDbState =
180212 | SimpleDbStateNew
181213 | SimpleDbStateOpened
182- | SimpleDbStateOpening ;
214+ | SimpleDbStateOpening
215+ | SimpleDbStateClosed ;
183216
184217/**
185218 * Provides a wrapper around IndexedDb with a simplified interface that uses
@@ -190,8 +223,7 @@ type SimpleDbState =
190223 */
191224export class SimpleDb {
192225 readonly debugId = `SimpleDb@${ generateUniqueDebugId ( ) } ` ;
193- private state : SimpleDbState = new SimpleDbStateNew ( ) ;
194- private databaseDeletedListener : DatabaseDeletedListener | null = null ;
226+ private state : SimpleDbState = new SimpleDbStateNew ( null ) ;
195227
196228 /** Deletes the specified database. */
197229 static delete ( name : string ) : Promise < void > {
@@ -331,26 +363,41 @@ export class SimpleDb {
331363 async ensureDb ( action : string ) : Promise < IdbDatabaseDebugIdPair > {
332364 while ( true ) {
333365 const currentState = this . state ;
334- if ( currentState . name === 'opening' ) {
366+ if ( currentState . name === 'closed' ) {
367+ console . trace (
368+ `zzyzx ${ this . debugId } ` +
369+ `ensureDb(${ JSON . stringify ( action ) } ) called after close()`
370+ ) ;
371+ dumpLogBuffer ( 'SimpleDb.ensureDb after close' ) ;
372+ throw new Error ( `${ this . debugId } has been closed` ) ;
373+ } else if ( currentState . name === 'opening' ) {
335374 await currentState . promise . catch ( _ => { } ) ;
336375 } else if ( currentState . name === 'opened' ) {
337376 return currentState . db ;
338377 } else {
339378 hardAssert ( currentState . name === 'new' , 0x56e8 , { state : this . state } ) ;
340379 const promise = this . openDb ( action ) ;
341- const openingState = new SimpleDbStateOpening ( promise ) ;
380+ const openingState = new SimpleDbStateOpening (
381+ promise ,
382+ currentState . databaseDeletedListener
383+ ) ;
342384 this . state = openingState ;
343385 try {
344386 const db = await promise ;
345387 if ( this . state === openingState ) {
346- this . state = new SimpleDbStateOpened ( db ) ;
388+ this . state = new SimpleDbStateOpened (
389+ db ,
390+ openingState . databaseDeletedListener
391+ ) ;
347392 return db ;
348393 } else {
349394 db . idbDatabase . close ( ) ;
350395 }
351396 } catch ( e ) {
352397 if ( this . state === openingState ) {
353- this . state = new SimpleDbStateNew ( ) ;
398+ this . state = new SimpleDbStateNew (
399+ this . state . databaseDeletedListener
400+ ) ;
354401 throw e ;
355402 }
356403 }
@@ -454,7 +501,9 @@ export class SimpleDb {
454501 `Received "versionchange" event with newVersion===null; ` +
455502 'notifying the registered DatabaseDeletedListener, if any'
456503 ) ;
457- this . databaseDeletedListener ?.( ) ;
504+ if ( 'databaseDeletedListener' in this . state ) {
505+ this . state . databaseDeletedListener ?.( ) ;
506+ }
458507 }
459508 } ,
460509 { passive : true }
@@ -471,9 +520,6 @@ export class SimpleDb {
471520 `in a web browser.`
472521 ) ;
473522 dumpLogBuffer ( 'SimpleDbCloseEvent' ) ;
474- if ( this . state . name === 'opened' && this . state . db . idbDatabase === db ) {
475- this . state = new SimpleDbStateNew ( ) ;
476- }
477523 } ,
478524 { passive : true }
479525 ) ;
@@ -484,10 +530,15 @@ export class SimpleDb {
484530 setDatabaseDeletedListener (
485531 databaseDeletedListener : DatabaseDeletedListener
486532 ) : void {
487- if ( this . databaseDeletedListener ) {
533+ if ( ! ( 'databaseDeletedListener' in this . state ) ) {
534+ return ;
535+ }
536+ if ( this . state . databaseDeletedListener ) {
488537 throw new Error ( 'setDatabaseDeletedListener() has already been called' ) ;
489538 }
490- this . databaseDeletedListener = databaseDeletedListener ;
539+ this . state = this . state . withDatabaseDeletedListener (
540+ databaseDeletedListener
541+ ) ;
491542 }
492543
493544 async runTransaction < T > (
@@ -568,7 +619,7 @@ export class SimpleDb {
568619 ) ;
569620
570621 if ( 'db' in this . state && dbBefore === this . state . db ) {
571- this . state = new SimpleDbStateNew ( ) ;
622+ this . state = new SimpleDbStateNew ( this . state . databaseDeletedListener ) ;
572623 logWarn (
573624 this . debugId ,
574625 `Transaction transactionId=${ transactionId } closing IDBDatabase ` +
@@ -586,11 +637,15 @@ export class SimpleDb {
586637 }
587638
588639 close ( ) : void {
640+ if ( this . state . name === 'closed' ) {
641+ dumpLogBuffer ( 'SimpleDb.close' ) ;
642+ return ;
643+ }
589644 logDebug ( this . debugId , 'close()' ) ;
590645 if ( 'db' in this . state ) {
591646 this . state . db . idbDatabase . close ( ) ;
592647 }
593- this . state = new SimpleDbStateNew ( ) ;
648+ this . state = new SimpleDbStateClosed ( ) ;
594649 }
595650}
596651
0 commit comments