Skip to content

Commit 469d314

Browse files
Merge 2d80ff5 into 2c1764d
2 parents 2c1764d + 2d80ff5 commit 469d314

File tree

18 files changed

+299
-363
lines changed

18 files changed

+299
-363
lines changed

packages-exp/functions-exp/test/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ export function createTestService(
6868
useFunctionsEmulator(
6969
functions,
7070
url.hostname,
71-
Number.parseInt(url.port, 10));
71+
Number.parseInt(url.port, 10)
72+
);
7273
}
7374
return functions;
7475
}

packages/auth/src/auth.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @license
3-
* Copyright 2017 Google Inc.
3+
* Copyright 2017 Google LLC
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.

packages/firebase/index.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,7 +1813,7 @@ declare namespace firebase.functions {
18131813
/**
18141814
* Changes this instance to point to a Cloud Functions emulator running
18151815
* locally. See https://firebase.google.com/docs/functions/local-emulator
1816-
*
1816+
*
18171817
* @deprecated Prefer the useEmulator(host, port) method.
18181818
* @param origin The origin of the local emulator, such as
18191819
* "http://localhost:5005".
@@ -3132,10 +3132,10 @@ declare namespace firebase.auth {
31323132
*/
31333133
useDeviceLanguage(): void;
31343134
/**
3135-
* Modify this Auth instance to communicate with the Firebase Auth emulator. This must be
3135+
* Modify this Auth instance to communicate with the Firebase Auth emulator. This must be
31363136
* called synchronously immediately following the first call to `firebase.auth()`. Do not use
31373137
* with production credentials as emulator traffic is not encrypted.
3138-
*
3138+
*
31393139
* @param url The URL at which the emulator is running (eg, 'http://localhost:9099')
31403140
*/
31413141
useEmulator(url: string): void;

packages/firestore/exp/src/api/components.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717

1818
import { FirebaseFirestore } from './database';
19-
import { PersistenceSettings } from '../../../src/core/firestore_client';
2019
import {
2120
MemoryOfflineComponentProvider,
2221
OfflineComponentProvider,
@@ -55,13 +54,10 @@ const onlineComponentProviders = new Map<
5554

5655
export async function setOfflineComponentProvider(
5756
firestore: FirebaseFirestore,
58-
persistenceSettings: PersistenceSettings,
5957
offlineComponentProvider: OfflineComponentProvider
6058
): Promise<void> {
6159
logDebug(LOG_TAG, 'Initializing OfflineComponentProvider');
6260
const configuration = await firestore._getConfiguration();
63-
configuration.persistenceSettings = persistenceSettings;
64-
6561
await offlineComponentProvider.initialize(configuration);
6662
firestore._setCredentialChangeListener(user =>
6763
// TODO(firestorexp): This should be a retryable IndexedDB operation
@@ -118,7 +114,6 @@ async function getOfflineComponentProvider(
118114
logDebug(LOG_TAG, 'Using default OfflineComponentProvider');
119115
await setOfflineComponentProvider(
120116
firestore,
121-
{ durable: false },
122117
new MemoryOfflineComponentProvider()
123118
);
124119
}

packages/firestore/exp/src/api/database.ts

Lines changed: 94 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
ComponentConfiguration,
3030
IndexedDbOfflineComponentProvider,
3131
MultiTabOfflineComponentProvider,
32+
OfflineComponentProvider,
3233
OnlineComponentProvider
3334
} from '../../../src/core/component_provider';
3435
import {
@@ -66,6 +67,11 @@ import { PersistenceSettings } from '../../../exp-types';
6667

6768
const LOG_TAG = 'Firestore';
6869

70+
/** DOMException error code constants. */
71+
const DOM_EXCEPTION_INVALID_STATE = 11;
72+
const DOM_EXCEPTION_ABORTED = 20;
73+
const DOM_EXCEPTION_QUOTA_EXCEEDED = 22;
74+
6975
export interface Settings extends LiteSettings {
7076
cacheSizeBytes?: number;
7177
}
@@ -130,9 +136,7 @@ export class FirebaseFirestore
130136
clientId: this._clientId,
131137
credentials: this._credentials,
132138
initialUser: this._user,
133-
maxConcurrentLimboResolutions: MAX_CONCURRENT_LIMBO_RESOLUTIONS,
134-
// Note: This will be overwritten if IndexedDB persistence is enabled.
135-
persistenceSettings: { durable: false }
139+
maxConcurrentLimboResolutions: MAX_CONCURRENT_LIMBO_RESOLUTIONS
136140
};
137141
}
138142

@@ -259,23 +263,15 @@ export function enableIndexedDbPersistence(
259263

260264
const onlineComponentProvider = new OnlineComponentProvider();
261265
const offlineComponentProvider = new IndexedDbOfflineComponentProvider(
262-
onlineComponentProvider
266+
onlineComponentProvider,
267+
settings.cacheSizeBytes,
268+
persistenceSettings?.forceOwnership
269+
);
270+
return setPersistenceProviders(
271+
firestore,
272+
onlineComponentProvider,
273+
offlineComponentProvider
263274
);
264-
265-
return firestore._queue.enqueue(async () => {
266-
await setOfflineComponentProvider(
267-
firestore,
268-
{
269-
durable: true,
270-
synchronizeTabs: false,
271-
cacheSizeBytes:
272-
settings.cacheSizeBytes || LruParams.DEFAULT_CACHE_SIZE_BYTES,
273-
forceOwningTab: !!persistenceSettings?.forceOwnership
274-
},
275-
offlineComponentProvider
276-
);
277-
await setOnlineComponentProvider(firestore, onlineComponentProvider);
278-
});
279275
}
280276

281277
/**
@@ -313,22 +309,87 @@ export function enableMultiTabIndexedDbPersistence(
313309

314310
const onlineComponentProvider = new OnlineComponentProvider();
315311
const offlineComponentProvider = new MultiTabOfflineComponentProvider(
316-
onlineComponentProvider
312+
onlineComponentProvider,
313+
settings.cacheSizeBytes
317314
);
318-
return firestore._queue.enqueue(async () => {
319-
await setOfflineComponentProvider(
320-
firestore,
321-
{
322-
durable: true,
323-
synchronizeTabs: true,
324-
cacheSizeBytes:
325-
settings.cacheSizeBytes || LruParams.DEFAULT_CACHE_SIZE_BYTES,
326-
forceOwningTab: false
327-
},
328-
offlineComponentProvider
315+
return setPersistenceProviders(
316+
firestore,
317+
onlineComponentProvider,
318+
offlineComponentProvider
319+
);
320+
}
321+
322+
/**
323+
* Registers both the `OfflineComponentProvider` and `OnlineComponentProvider`.
324+
* If the operation fails with a recoverable error (see
325+
* `canRecoverFromIndexedDbError()` below), the returned Promise is rejected
326+
* but the client remains usable.
327+
*/
328+
function setPersistenceProviders(
329+
firestore: FirebaseFirestore,
330+
onlineComponentProvider: OnlineComponentProvider,
331+
offlineComponentProvider: OfflineComponentProvider
332+
): Promise<void> {
333+
const persistenceResult = new Deferred();
334+
return firestore._queue
335+
.enqueue(async () => {
336+
try {
337+
await setOfflineComponentProvider(firestore, offlineComponentProvider);
338+
await setOnlineComponentProvider(firestore, onlineComponentProvider);
339+
persistenceResult.resolve();
340+
} catch (e) {
341+
if (!canFallbackFromIndexedDbError(e)) {
342+
throw e;
343+
}
344+
console.warn(
345+
'Error enabling offline persistence. Falling back to ' +
346+
'persistence disabled: ' +
347+
e
348+
);
349+
persistenceResult.reject(e);
350+
}
351+
})
352+
.then(() => persistenceResult.promise);
353+
}
354+
355+
/**
356+
* Decides whether the provided error allows us to gracefully disable
357+
* persistence (as opposed to crashing the client).
358+
*/
359+
// TODO(schmidt-sebastian): Remove `export` in
360+
// https://github.com/firebase/firebase-js-sdk/pull/3901
361+
export function canFallbackFromIndexedDbError(
362+
error: FirestoreError | DOMException
363+
): boolean {
364+
if (error.name === 'FirebaseError') {
365+
return (
366+
error.code === Code.FAILED_PRECONDITION ||
367+
error.code === Code.UNIMPLEMENTED
329368
);
330-
await setOnlineComponentProvider(firestore, onlineComponentProvider);
331-
});
369+
} else if (
370+
typeof DOMException !== 'undefined' &&
371+
error instanceof DOMException
372+
) {
373+
// There are a few known circumstances where we can open IndexedDb but
374+
// trying to read/write will fail (e.g. quota exceeded). For
375+
// well-understood cases, we attempt to detect these and then gracefully
376+
// fall back to memory persistence.
377+
// NOTE: Rather than continue to add to this list, we could decide to
378+
// always fall back, with the risk that we might accidentally hide errors
379+
// representing actual SDK bugs.
380+
return (
381+
// When the browser is out of quota we could get either quota exceeded
382+
// or an aborted error depending on whether the error happened during
383+
// schema migration.
384+
error.code === DOM_EXCEPTION_QUOTA_EXCEEDED ||
385+
error.code === DOM_EXCEPTION_ABORTED ||
386+
// Firefox Private Browsing mode disables IndexedDb and returns
387+
// INVALID_STATE for any usage.
388+
error.code === DOM_EXCEPTION_INVALID_STATE
389+
);
390+
}
391+
392+
return true;
332393
}
333394

334395
/**

packages/firestore/index.memory.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@
1818
import firebase from '@firebase/app';
1919
import { FirebaseNamespace } from '@firebase/app-types';
2020

21-
import { Firestore } from './src/api/database';
22-
import {
23-
MemoryOfflineComponentProvider,
24-
OnlineComponentProvider
25-
} from './src/core/component_provider';
21+
import { Firestore, MemoryPersistenceProvider } from './src/api/database';
2622
import { configureForFirebase } from './src/config';
2723

2824
import './register-module';
@@ -35,13 +31,7 @@ import { name, version } from './package.json';
3531
export function registerFirestore(instance: FirebaseNamespace): void {
3632
configureForFirebase(
3733
instance,
38-
(app, auth) =>
39-
new Firestore(
40-
app,
41-
auth,
42-
new MemoryOfflineComponentProvider(),
43-
new OnlineComponentProvider()
44-
)
34+
(app, auth) => new Firestore(app, auth, new MemoryPersistenceProvider())
4535
);
4636
instance.registerVersion(name, version);
4737
}

packages/firestore/index.node.memory.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@
1818
import firebase from '@firebase/app';
1919
import { FirebaseNamespace } from '@firebase/app-types';
2020

21-
import { Firestore } from './src/api/database';
22-
import {
23-
MemoryOfflineComponentProvider,
24-
OnlineComponentProvider
25-
} from './src/core/component_provider';
21+
import { Firestore, MemoryPersistenceProvider } from './src/api/database';
2622
import { configureForFirebase } from './src/config';
2723
import './register-module';
2824

@@ -35,13 +31,7 @@ import { name, version } from './package.json';
3531
export function registerFirestore(instance: FirebaseNamespace): void {
3632
configureForFirebase(
3733
instance,
38-
(app, auth) =>
39-
new Firestore(
40-
app,
41-
auth,
42-
new MemoryOfflineComponentProvider(),
43-
new OnlineComponentProvider()
44-
)
34+
(app, auth) => new Firestore(app, auth, new MemoryPersistenceProvider())
4535
);
4636
instance.registerVersion(name, version, 'node');
4737
}

packages/firestore/index.node.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@
1717
import firebase from '@firebase/app';
1818
import { FirebaseNamespace } from '@firebase/app-types';
1919

20-
import { Firestore } from './src/api/database';
21-
import {
22-
MultiTabOfflineComponentProvider,
23-
OnlineComponentProvider
24-
} from './src/core/component_provider';
20+
import { Firestore, IndexedDbPersistenceProvider } from './src/api/database';
2521
import { configureForFirebase } from './src/config';
2622

2723
import './register-module';
@@ -34,16 +30,7 @@ import { name, version } from './package.json';
3430
*/
3531
export function registerFirestore(instance: FirebaseNamespace): void {
3632
configureForFirebase(instance, (app, auth) => {
37-
const onlineComponentProvider = new OnlineComponentProvider();
38-
const offlineComponentProvider = new MultiTabOfflineComponentProvider(
39-
onlineComponentProvider
40-
);
41-
return new Firestore(
42-
app,
43-
auth,
44-
offlineComponentProvider,
45-
onlineComponentProvider
46-
);
33+
return new Firestore(app, auth, new IndexedDbPersistenceProvider());
4734
});
4835
instance.registerVersion(name, version, 'node');
4936
}

packages/firestore/index.rn.memory.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@
1818
import firebase from '@firebase/app';
1919
import { FirebaseNamespace } from '@firebase/app-types';
2020

21-
import { Firestore } from './src/api/database';
22-
import {
23-
MemoryOfflineComponentProvider,
24-
OnlineComponentProvider
25-
} from './src/core/component_provider';
21+
import { Firestore, MemoryPersistenceProvider } from './src/api/database';
2622
import { configureForFirebase } from './src/config';
2723

2824
import './register-module';
@@ -36,13 +32,7 @@ import { name, version } from './package.json';
3632
export function registerFirestore(instance: FirebaseNamespace): void {
3733
configureForFirebase(
3834
instance,
39-
(app, auth) =>
40-
new Firestore(
41-
app,
42-
auth,
43-
new MemoryOfflineComponentProvider(),
44-
new OnlineComponentProvider()
45-
)
35+
(app, auth) => new Firestore(app, auth, new MemoryPersistenceProvider())
4636
);
4737
instance.registerVersion(name, version, 'rn');
4838
}

packages/firestore/index.rn.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@
1717
import firebase from '@firebase/app';
1818
import { FirebaseNamespace } from '@firebase/app-types';
1919

20-
import { Firestore } from './src/api/database';
21-
import {
22-
MultiTabOfflineComponentProvider,
23-
OnlineComponentProvider
24-
} from './src/core/component_provider';
20+
import { Firestore, IndexedDbPersistenceProvider } from './src/api/database';
2521
import { configureForFirebase } from './src/config';
2622

2723
import './register-module';
@@ -33,16 +29,7 @@ import { name, version } from './package.json';
3329
*/
3430
export function registerFirestore(instance: FirebaseNamespace): void {
3531
configureForFirebase(instance, (app, auth) => {
36-
const onlineComponentProvider = new OnlineComponentProvider();
37-
const offlineComponentProvider = new MultiTabOfflineComponentProvider(
38-
onlineComponentProvider
39-
);
40-
return new Firestore(
41-
app,
42-
auth,
43-
offlineComponentProvider,
44-
onlineComponentProvider
45-
);
32+
return new Firestore(app, auth, new IndexedDbPersistenceProvider());
4633
});
4734
instance.registerVersion(name, version, 'rn');
4835
}

0 commit comments

Comments
 (0)