@@ -197,6 +197,7 @@ export class IndexedDbPersistence implements Persistence {
197
197
queue : AsyncQueue ;
198
198
serializer : JsonProtoSerializer ;
199
199
sequenceNumberSyncer : SequenceNumberSyncer ;
200
+ force : boolean ;
200
201
} ) : Promise < IndexedDbPersistence > {
201
202
if ( ! IndexedDbPersistence . isAvailable ( ) ) {
202
203
throw new FirestoreError (
@@ -213,14 +214,15 @@ export class IndexedDbPersistence implements Persistence {
213
214
options . lruParams ,
214
215
options . queue ,
215
216
options . serializer ,
216
- options . sequenceNumberSyncer
217
+ options . sequenceNumberSyncer ,
218
+ options . force
217
219
) ;
218
220
await persistence . start ( ) ;
219
221
return persistence ;
220
222
}
221
223
222
224
private readonly document : Document | null ;
223
- private readonly window : Window ;
225
+ private readonly window : Window | null ;
224
226
225
227
// Technically these types should be `| undefined` because they are
226
228
// initialized asynchronously by start(), but that would be more misleading
@@ -254,7 +256,7 @@ export class IndexedDbPersistence implements Persistence {
254
256
private readonly queryCache : IndexedDbQueryCache ;
255
257
private readonly indexManager : IndexedDbIndexManager ;
256
258
private readonly remoteDocumentCache : IndexedDbRemoteDocumentCache ;
257
- private readonly webStorage : Storage ;
259
+ private readonly webStorage : Storage | null ;
258
260
readonly referenceDelegate : IndexedDbLruDelegate ;
259
261
260
262
private constructor (
@@ -265,7 +267,8 @@ export class IndexedDbPersistence implements Persistence {
265
267
lruParams : LruParams ,
266
268
private readonly queue : AsyncQueue ,
267
269
serializer : JsonProtoSerializer ,
268
- private readonly sequenceNumberSyncer : SequenceNumberSyncer
270
+ private readonly sequenceNumberSyncer : SequenceNumberSyncer ,
271
+ private readonly force : boolean
269
272
) {
270
273
this . referenceDelegate = new IndexedDbLruDelegate ( this , lruParams ) ;
271
274
this . dbName = persistenceKey + IndexedDbPersistence . MAIN_DATABASE ;
@@ -281,13 +284,14 @@ export class IndexedDbPersistence implements Persistence {
281
284
this . indexManager ,
282
285
/*keepDocumentChangeLog=*/ this . allowTabSynchronization
283
286
) ;
287
+ this . window = platform . window ;
284
288
if ( platform . window && platform . window . localStorage ) {
285
- this . window = platform . window ;
286
- this . webStorage = this . window . localStorage ;
289
+ this . webStorage = platform . window . localStorage ;
287
290
} else {
288
- throw new FirestoreError (
289
- Code . UNIMPLEMENTED ,
290
- 'IndexedDB persistence is only available on platforms that support LocalStorage.'
291
+ this . webStorage = null ;
292
+ log . error (
293
+ LOG_TAG ,
294
+ 'LocalStorage is unavailable. Multi-tab functionality may not be supported.'
291
295
) ;
292
296
}
293
297
}
@@ -299,7 +303,6 @@ export class IndexedDbPersistence implements Persistence {
299
303
*/
300
304
private start ( ) : Promise < void > {
301
305
assert ( ! this . started , 'IndexedDbPersistence double-started!' ) ;
302
- assert ( this . window !== null , "Expected 'window' to be defined" ) ;
303
306
304
307
return SimpleDb . openOrCreate (
305
308
this . dbName ,
@@ -526,9 +529,11 @@ export class IndexedDbPersistence implements Persistence {
526
529
// the client atomically, but we can't. So we opt to delete the IndexedDb
527
530
// entries first to avoid potentially reviving a zombied client.
528
531
inactiveClients . forEach ( inactiveClient => {
529
- this . window . localStorage . removeItem (
530
- this . zombiedClientLocalStorageKey ( inactiveClient . clientId )
531
- ) ;
532
+ if ( this . webStorage ) {
533
+ this . webStorage . removeItem (
534
+ this . zombiedClientLocalStorageKey ( inactiveClient . clientId )
535
+ ) ;
536
+ }
532
537
} ) ;
533
538
}
534
539
}
@@ -551,6 +556,10 @@ export class IndexedDbPersistence implements Persistence {
551
556
552
557
/** Checks whether `client` is the local client. */
553
558
private isLocalClient ( client : DbPrimaryClient | null ) : boolean {
559
+ console . error ( 'this id' , this . clientId ) ;
560
+ if ( client ) {
561
+ console . error ( 'client id' , client . ownerId ) ;
562
+ }
554
563
return client ? client . ownerId === this . clientId : false ;
555
564
}
556
565
@@ -590,6 +599,9 @@ export class IndexedDbPersistence implements Persistence {
590
599
}
591
600
592
601
if ( ! this . isLocalClient ( currentPrimary ) ) {
602
+ if ( this . force ) {
603
+ return true ;
604
+ }
593
605
if ( ! currentPrimary ! . allowTabSynchronization ) {
594
606
// Fail the `canActAsPrimary` check if the current leaseholder has
595
607
// not opted into multi-tab synchronization. If this happens at
@@ -974,6 +986,9 @@ export class IndexedDbPersistence implements Persistence {
974
986
* handler.
975
987
*/
976
988
private attachWindowUnloadHook ( ) : void {
989
+ if ( ! this . window ) {
990
+ return ;
991
+ }
977
992
if ( typeof this . window . addEventListener === 'function' ) {
978
993
this . windowUnloadHandler = ( ) => {
979
994
// Note: In theory, this should be scheduled on the AsyncQueue since it
@@ -992,6 +1007,9 @@ export class IndexedDbPersistence implements Persistence {
992
1007
}
993
1008
994
1009
private detachWindowUnloadHook ( ) : void {
1010
+ if ( ! this . window ) {
1011
+ return ;
1012
+ }
995
1013
if ( this . windowUnloadHandler ) {
996
1014
assert (
997
1015
typeof this . window . removeEventListener === 'function' ,
@@ -1008,6 +1026,9 @@ export class IndexedDbPersistence implements Persistence {
1008
1026
* cleanup logic in `shutdown()`.
1009
1027
*/
1010
1028
private isClientZombied ( clientId : ClientId ) : boolean {
1029
+ if ( ! this . webStorage ) {
1030
+ return false ;
1031
+ }
1011
1032
try {
1012
1033
const isZombied =
1013
1034
this . webStorage . getItem ( this . zombiedClientLocalStorageKey ( clientId ) ) !==
@@ -1031,6 +1052,9 @@ export class IndexedDbPersistence implements Persistence {
1031
1052
* clients are ignored during primary tab selection.
1032
1053
*/
1033
1054
private markClientZombied ( ) : void {
1055
+ if ( ! this . webStorage ) {
1056
+ return ;
1057
+ }
1034
1058
try {
1035
1059
this . webStorage . setItem (
1036
1060
this . zombiedClientLocalStorageKey ( this . clientId ) ,
@@ -1044,6 +1068,9 @@ export class IndexedDbPersistence implements Persistence {
1044
1068
1045
1069
/** Removes the zombied client entry if it exists. */
1046
1070
private removeClientZombiedEntry ( ) : void {
1071
+ if ( ! this . webStorage ) {
1072
+ return ;
1073
+ }
1047
1074
try {
1048
1075
this . webStorage . removeItem (
1049
1076
this . zombiedClientLocalStorageKey ( this . clientId )
0 commit comments