Skip to content

Commit f0287d4

Browse files
author
Brian Chen
committed
cleaned up
1 parent 806aabb commit f0287d4

File tree

6 files changed

+80
-19
lines changed

6 files changed

+80
-19
lines changed

packages/firebase/index.d.ts

+8
Original file line numberDiff line numberDiff line change
@@ -6226,6 +6226,14 @@ declare namespace firebase.firestore {
62266226
* multiple tabs, please use `synchronizeTabs: true` instead.
62276227
*/
62286228
experimentalTabSynchronization?: boolean;
6229+
6230+
/**
6231+
* Whether to force enable persistence for the client. This cannot be used
6232+
* with `synchronizeTabs:true` and is primarily intended for use with Web
6233+
* Workers. Setting this to 'true' will enable persistence, but cause other
6234+
* tabs using persistence to fail.
6235+
*/
6236+
experimentalForce?: boolean;
62296237
}
62306238

62316239
export type LogLevel = 'debug' | 'error' | 'silent';

packages/firestore-types/index.d.ts

+8
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ export interface PersistenceSettings {
122122
* multiple tabs, please use `synchronizeTabs: true` instead.
123123
*/
124124
experimentalTabSynchronization?: boolean;
125+
126+
/**
127+
* Whether to force enable persistence for the client. This cannot be used
128+
* with `synchronizeTabs:true` and is primarily intended for use with Web
129+
* Workers. Setting this to 'true' will enable persistence, but cause other
130+
* tabs using persistence to fail.
131+
*/
132+
experimentalForce?: boolean;
125133
}
126134

127135
export type LogLevel = 'debug' | 'error' | 'silent';

packages/firestore/src/api/database.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
386386
}
387387

388388
let synchronizeTabs = false;
389+
let experimentalForce = false;
389390

390391
if (settings) {
391392
if (settings.experimentalTabSynchronization !== undefined) {
@@ -402,12 +403,16 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
402403
: settings.experimentalTabSynchronization,
403404
DEFAULT_SYNCHRONIZE_TABS
404405
);
406+
experimentalForce = settings.experimentalForce
407+
? settings.experimentalForce
408+
: false;
405409
}
406410

407411
return this.configureClient(
408412
new IndexedDbPersistenceSettings(
409413
this._settings.cacheSizeBytes,
410-
synchronizeTabs
414+
synchronizeTabs,
415+
experimentalForce
411416
)
412417
);
413418
}

packages/firestore/src/core/firestore_client.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ const DOM_EXCEPTION_QUOTA_EXCEEDED = 22;
7373
export class IndexedDbPersistenceSettings {
7474
constructor(
7575
readonly cacheSizeBytes: number,
76-
readonly synchronizeTabs: boolean
76+
readonly synchronizeTabs: boolean,
77+
readonly force: boolean
7778
) {}
7879

7980
lruParams(): LruParams {
@@ -343,7 +344,8 @@ export class FirestoreClient {
343344
) {
344345
throw new FirestoreError(
345346
Code.UNIMPLEMENTED,
346-
'IndexedDB persistence is only available on platforms that support LocalStorage.'
347+
'IndexedDB persistence with synchronizedTabs is only available on ' +
348+
'platforms that support LocalStorage.'
347349
);
348350
}
349351

@@ -358,7 +360,6 @@ export class FirestoreClient {
358360
user
359361
)
360362
: new MemorySharedClientState();
361-
362363
const persistence = await IndexedDbPersistence.createIndexedDbPersistence(
363364
{
364365
allowTabSynchronization: settings.synchronizeTabs,
@@ -368,7 +369,8 @@ export class FirestoreClient {
368369
queue: this.asyncQueue,
369370
serializer,
370371
lruParams,
371-
sequenceNumberSyncer: this.sharedClientState
372+
sequenceNumberSyncer: this.sharedClientState,
373+
force: settings.force
372374
}
373375
);
374376

packages/firestore/src/local/indexeddb_persistence.ts

+40-13
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ export class IndexedDbPersistence implements Persistence {
197197
queue: AsyncQueue;
198198
serializer: JsonProtoSerializer;
199199
sequenceNumberSyncer: SequenceNumberSyncer;
200+
force: boolean;
200201
}): Promise<IndexedDbPersistence> {
201202
if (!IndexedDbPersistence.isAvailable()) {
202203
throw new FirestoreError(
@@ -213,14 +214,15 @@ export class IndexedDbPersistence implements Persistence {
213214
options.lruParams,
214215
options.queue,
215216
options.serializer,
216-
options.sequenceNumberSyncer
217+
options.sequenceNumberSyncer,
218+
options.force
217219
);
218220
await persistence.start();
219221
return persistence;
220222
}
221223

222224
private readonly document: Document | null;
223-
private readonly window: Window;
225+
private readonly window: Window | null;
224226

225227
// Technically these types should be `| undefined` because they are
226228
// initialized asynchronously by start(), but that would be more misleading
@@ -254,7 +256,7 @@ export class IndexedDbPersistence implements Persistence {
254256
private readonly queryCache: IndexedDbQueryCache;
255257
private readonly indexManager: IndexedDbIndexManager;
256258
private readonly remoteDocumentCache: IndexedDbRemoteDocumentCache;
257-
private readonly webStorage: Storage;
259+
private readonly webStorage: Storage | null;
258260
readonly referenceDelegate: IndexedDbLruDelegate;
259261

260262
private constructor(
@@ -265,7 +267,8 @@ export class IndexedDbPersistence implements Persistence {
265267
lruParams: LruParams,
266268
private readonly queue: AsyncQueue,
267269
serializer: JsonProtoSerializer,
268-
private readonly sequenceNumberSyncer: SequenceNumberSyncer
270+
private readonly sequenceNumberSyncer: SequenceNumberSyncer,
271+
private readonly force: boolean
269272
) {
270273
this.referenceDelegate = new IndexedDbLruDelegate(this, lruParams);
271274
this.dbName = persistenceKey + IndexedDbPersistence.MAIN_DATABASE;
@@ -281,13 +284,14 @@ export class IndexedDbPersistence implements Persistence {
281284
this.indexManager,
282285
/*keepDocumentChangeLog=*/ this.allowTabSynchronization
283286
);
287+
this.window = platform.window;
284288
if (platform.window && platform.window.localStorage) {
285-
this.window = platform.window;
286-
this.webStorage = this.window.localStorage;
289+
this.webStorage = platform.window.localStorage;
287290
} 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.'
291295
);
292296
}
293297
}
@@ -299,7 +303,6 @@ export class IndexedDbPersistence implements Persistence {
299303
*/
300304
private start(): Promise<void> {
301305
assert(!this.started, 'IndexedDbPersistence double-started!');
302-
assert(this.window !== null, "Expected 'window' to be defined");
303306

304307
return SimpleDb.openOrCreate(
305308
this.dbName,
@@ -526,9 +529,11 @@ export class IndexedDbPersistence implements Persistence {
526529
// the client atomically, but we can't. So we opt to delete the IndexedDb
527530
// entries first to avoid potentially reviving a zombied client.
528531
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+
}
532537
});
533538
}
534539
}
@@ -551,6 +556,10 @@ export class IndexedDbPersistence implements Persistence {
551556

552557
/** Checks whether `client` is the local client. */
553558
private isLocalClient(client: DbPrimaryClient | null): boolean {
559+
console.error('this id', this.clientId);
560+
if (client) {
561+
console.error('client id', client.ownerId);
562+
}
554563
return client ? client.ownerId === this.clientId : false;
555564
}
556565

@@ -590,6 +599,9 @@ export class IndexedDbPersistence implements Persistence {
590599
}
591600

592601
if (!this.isLocalClient(currentPrimary)) {
602+
if (this.force) {
603+
return true;
604+
}
593605
if (!currentPrimary!.allowTabSynchronization) {
594606
// Fail the `canActAsPrimary` check if the current leaseholder has
595607
// not opted into multi-tab synchronization. If this happens at
@@ -974,6 +986,9 @@ export class IndexedDbPersistence implements Persistence {
974986
* handler.
975987
*/
976988
private attachWindowUnloadHook(): void {
989+
if (!this.window) {
990+
return;
991+
}
977992
if (typeof this.window.addEventListener === 'function') {
978993
this.windowUnloadHandler = () => {
979994
// Note: In theory, this should be scheduled on the AsyncQueue since it
@@ -992,6 +1007,9 @@ export class IndexedDbPersistence implements Persistence {
9921007
}
9931008

9941009
private detachWindowUnloadHook(): void {
1010+
if (!this.window) {
1011+
return;
1012+
}
9951013
if (this.windowUnloadHandler) {
9961014
assert(
9971015
typeof this.window.removeEventListener === 'function',
@@ -1008,6 +1026,9 @@ export class IndexedDbPersistence implements Persistence {
10081026
* cleanup logic in `shutdown()`.
10091027
*/
10101028
private isClientZombied(clientId: ClientId): boolean {
1029+
if (!this.webStorage) {
1030+
return false;
1031+
}
10111032
try {
10121033
const isZombied =
10131034
this.webStorage.getItem(this.zombiedClientLocalStorageKey(clientId)) !==
@@ -1031,6 +1052,9 @@ export class IndexedDbPersistence implements Persistence {
10311052
* clients are ignored during primary tab selection.
10321053
*/
10331054
private markClientZombied(): void {
1055+
if (!this.webStorage) {
1056+
return;
1057+
}
10341058
try {
10351059
this.webStorage.setItem(
10361060
this.zombiedClientLocalStorageKey(this.clientId),
@@ -1044,6 +1068,9 @@ export class IndexedDbPersistence implements Persistence {
10441068

10451069
/** Removes the zombied client entry if it exists. */
10461070
private removeClientZombiedEntry(): void {
1071+
if (!this.webStorage) {
1072+
return;
1073+
}
10471074
try {
10481075
this.webStorage.removeItem(
10491076
this.zombiedClientLocalStorageKey(this.clientId)

packages/firestore/src/local/simple_db.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,14 @@ export class SimpleDb {
6666
// suggests IE9 and older WebKit browsers handle upgrade
6767
// differently. They expect setVersion, as described here:
6868
// https://developer.mozilla.org/en-US/docs/Web/API/IDBVersionChangeRequest/setVersion
69-
const request = window.indexedDB.open(name, version);
69+
70+
let request: IDBOpenDBRequest;
71+
// Support Web Workers, which don't have `window` global variable.
72+
if (indexedDB !== undefined) {
73+
request = indexedDB.open(name, version);
74+
} else {
75+
request = window.indexedDB.open(name, version);
76+
}
7077

7178
request.onsuccess = (event: Event) => {
7279
const db = (event.target as IDBOpenDBRequest).result;
@@ -132,6 +139,10 @@ export class SimpleDb {
132139

133140
/** Returns true if IndexedDB is available in the current environment. */
134141
static isAvailable(): boolean {
142+
// If IndexedDb is available directly (ex: in case of web workers).
143+
if (typeof indexedDB !== 'undefined') {
144+
return true;
145+
}
135146
if (typeof window === 'undefined' || window.indexedDB == null) {
136147
return false;
137148
}

0 commit comments

Comments
 (0)