@@ -746,6 +746,7 @@ export class IndexedDbProvider extends DbProvider {
746746// DbTransaction implementation for the IndexedDB DbProvider.
747747export class IndexedDbTransaction implements DbTransaction {
748748 private _stores : IDBObjectStore [ ] ;
749+ private _indexStoreMap : Map < string , IDBObjectStore > ;
749750
750751 constructor (
751752 private _trans : IDBTransaction ,
@@ -760,6 +761,28 @@ export class IndexedDbTransaction implements DbTransaction {
760761 this . _trans . objectStore ( storeName )
761762 ) ;
762763
764+ // Eagerly capture multi-entry/fullText index object stores while the transaction is still
765+ // in "active" state. Deferring this to getStore() risks an InvalidStateError if the event
766+ // loop runs between openTransaction() and the first getStore() call, causing the IDB
767+ // transaction to auto-commit before the objectStore() call.
768+ this . _indexStoreMap = new Map < string , IDBObjectStore > ( ) ;
769+ if ( _fakeComplicatedKeys ) {
770+ each ( this . _transToken . storeNames , ( storeName ) => {
771+ const storeSchema = find ( _schema . stores , ( s ) => s . name === storeName ) ;
772+ if ( storeSchema ?. indexes ) {
773+ each ( storeSchema . indexes , ( indexSchema ) => {
774+ if ( indexSchema . multiEntry || indexSchema . fullText ) {
775+ const indexStoreName = storeSchema . name + "_" + indexSchema . name ;
776+ this . _indexStoreMap . set (
777+ indexStoreName ,
778+ this . _trans . objectStore ( indexStoreName )
779+ ) ;
780+ }
781+ } ) ;
782+ }
783+ } ) ;
784+ }
785+
763786 if ( lockHelper ) {
764787 // Chromium seems to have a bug in their indexeddb implementation that lets it start a timeout
765788 // while the app is in the middle of a commit (it does a two-phase commit). It can then finish
@@ -847,12 +870,17 @@ export class IndexedDbTransaction implements DbTransaction {
847870
848871 const indexStores : IDBObjectStore [ ] = [ ] ;
849872 if ( this . _fakeComplicatedKeys && storeSchema . indexes ) {
850- // Pull the alternate multientry stores in as well
873+ // Pull the alternate multientry stores in as well, using the map populated eagerly in the
874+ // constructor to avoid calling objectStore() after an async yield (which would throw
875+ // InvalidStateError if the transaction has already auto-committed).
851876 each ( storeSchema . indexes , ( indexSchema ) => {
852877 if ( indexSchema . multiEntry || indexSchema . fullText ) {
853- indexStores . push (
854- this . _trans . objectStore ( storeSchema . name + "_" + indexSchema . name )
855- ) ;
878+ const indexStoreName = storeSchema . name + "_" + indexSchema . name ;
879+ const indexStore = this . _indexStoreMap . get ( indexStoreName ) ;
880+ if ( ! indexStore ) {
881+ throw new Error ( "Index store not found in transaction: " + indexStoreName ) ;
882+ }
883+ indexStores . push ( indexStore ) ;
856884 }
857885 } ) ;
858886 }
0 commit comments