mirror of
https://github.com/hanzoai/firebase-js-sdk.git
synced 2026-09-24 16:59:10 +00:00
Warn instead of throw for idb errors in core app (#6480)
This commit is contained in:
committed by
GitHub
parent
1df9db9510
commit
7471fbb251
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@firebase/app': patch
|
||||
---
|
||||
|
||||
Prevent core app from throwing if IndexedDB heartbeat functions throw.
|
||||
+16
-16
@@ -24,10 +24,10 @@ export const enum AppError {
|
||||
APP_DELETED = 'app-deleted',
|
||||
INVALID_APP_ARGUMENT = 'invalid-app-argument',
|
||||
INVALID_LOG_ARGUMENT = 'invalid-log-argument',
|
||||
STORAGE_OPEN = 'storage-open',
|
||||
STORAGE_GET = 'storage-get',
|
||||
STORAGE_WRITE = 'storage-set',
|
||||
STORAGE_DELETE = 'storage-delete'
|
||||
IDB_OPEN = 'idb-open',
|
||||
IDB_GET = 'idb-get',
|
||||
IDB_WRITE = 'idb-set',
|
||||
IDB_DELETE = 'idb-delete'
|
||||
}
|
||||
|
||||
const ERRORS: ErrorMap<AppError> = {
|
||||
@@ -43,14 +43,14 @@ const ERRORS: ErrorMap<AppError> = {
|
||||
'Firebase App instance.',
|
||||
[AppError.INVALID_LOG_ARGUMENT]:
|
||||
'First argument to `onLog` must be null or a function.',
|
||||
[AppError.STORAGE_OPEN]:
|
||||
'Error thrown when opening storage. Original error: {$originalErrorMessage}.',
|
||||
[AppError.STORAGE_GET]:
|
||||
'Error thrown when reading from storage. Original error: {$originalErrorMessage}.',
|
||||
[AppError.STORAGE_WRITE]:
|
||||
'Error thrown when writing to storage. Original error: {$originalErrorMessage}.',
|
||||
[AppError.STORAGE_DELETE]:
|
||||
'Error thrown when deleting from storage. Original error: {$originalErrorMessage}.'
|
||||
[AppError.IDB_OPEN]:
|
||||
'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
|
||||
[AppError.IDB_GET]:
|
||||
'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
|
||||
[AppError.IDB_WRITE]:
|
||||
'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
|
||||
[AppError.IDB_DELETE]:
|
||||
'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.'
|
||||
};
|
||||
|
||||
interface ErrorParams {
|
||||
@@ -59,10 +59,10 @@ interface ErrorParams {
|
||||
[AppError.DUPLICATE_APP]: { appName: string };
|
||||
[AppError.APP_DELETED]: { appName: string };
|
||||
[AppError.INVALID_APP_ARGUMENT]: { appName: string };
|
||||
[AppError.STORAGE_OPEN]: { originalErrorMessage?: string };
|
||||
[AppError.STORAGE_GET]: { originalErrorMessage?: string };
|
||||
[AppError.STORAGE_WRITE]: { originalErrorMessage?: string };
|
||||
[AppError.STORAGE_DELETE]: { originalErrorMessage?: string };
|
||||
[AppError.IDB_OPEN]: { originalErrorMessage?: string };
|
||||
[AppError.IDB_GET]: { originalErrorMessage?: string };
|
||||
[AppError.IDB_WRITE]: { originalErrorMessage?: string };
|
||||
[AppError.IDB_DELETE]: { originalErrorMessage?: string };
|
||||
}
|
||||
|
||||
export const ERROR_FACTORY = new ErrorFactory<AppError, ErrorParams>(
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2022 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { expect } from 'chai';
|
||||
import '../test/setup';
|
||||
import { match, stub } from 'sinon';
|
||||
import {
|
||||
readHeartbeatsFromIndexedDB,
|
||||
writeHeartbeatsToIndexedDB
|
||||
} from './indexeddb';
|
||||
import { FirebaseApp } from './public-types';
|
||||
import { AppError } from './errors';
|
||||
import { HeartbeatsInIndexedDB } from './types';
|
||||
|
||||
/**
|
||||
* Mostly testing failure cases. heartbeatService.test.ts tests read-write
|
||||
* more extensively.
|
||||
*/
|
||||
|
||||
describe('IndexedDB functions', () => {
|
||||
it('readHeartbeatsFromIndexedDB warns if IndexedDB.open() throws', async () => {
|
||||
const warnStub = stub(console, 'warn');
|
||||
if (typeof window !== 'undefined') {
|
||||
// Ensure that indexedDB.open() fails in browser. It will always fail in Node.
|
||||
stub(window.indexedDB, 'open').throws(new Error('abcd'));
|
||||
await readHeartbeatsFromIndexedDB({
|
||||
name: 'testname',
|
||||
options: { appId: 'test-app-id' }
|
||||
} as FirebaseApp);
|
||||
expect(warnStub).to.be.calledWith(match.any, match(AppError.IDB_GET));
|
||||
} else {
|
||||
await readHeartbeatsFromIndexedDB({
|
||||
name: 'testname',
|
||||
options: { appId: 'test-app-id' }
|
||||
} as FirebaseApp);
|
||||
expect(warnStub).to.be.calledWith(match.any, match(AppError.IDB_GET));
|
||||
}
|
||||
});
|
||||
it('writeHeartbeatsToIndexedDB warns if IndexedDB.open() throws', async () => {
|
||||
const warnStub = stub(console, 'warn');
|
||||
if (typeof window !== 'undefined') {
|
||||
// Ensure that indexedDB.open() fails in browser. It will always fail in Node.
|
||||
stub(window.indexedDB, 'open').throws(new Error('abcd'));
|
||||
await writeHeartbeatsToIndexedDB(
|
||||
{
|
||||
name: 'testname',
|
||||
options: { appId: 'test-app-id' }
|
||||
} as FirebaseApp,
|
||||
{} as HeartbeatsInIndexedDB
|
||||
);
|
||||
expect(warnStub).to.be.calledWith(match.any, match(AppError.IDB_WRITE));
|
||||
} else {
|
||||
await writeHeartbeatsToIndexedDB(
|
||||
{
|
||||
name: 'testname',
|
||||
options: { appId: 'test-app-id' }
|
||||
} as FirebaseApp,
|
||||
{} as HeartbeatsInIndexedDB
|
||||
);
|
||||
expect(warnStub).to.be.calledWith(match.any, match(AppError.IDB_WRITE));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -15,10 +15,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FirebaseError } from '@firebase/util';
|
||||
import { DBSchema, openDB, IDBPDatabase } from 'idb';
|
||||
import { AppError, ERROR_FACTORY } from './errors';
|
||||
import { FirebaseApp } from './public-types';
|
||||
import { HeartbeatsInIndexedDB } from './types';
|
||||
import { logger } from './logger';
|
||||
|
||||
const DB_NAME = 'firebase-heartbeat-database';
|
||||
const DB_VERSION = 1;
|
||||
@@ -47,7 +49,7 @@ function getDbPromise(): Promise<IDBPDatabase<AppDB>> {
|
||||
}
|
||||
}
|
||||
}).catch(e => {
|
||||
throw ERROR_FACTORY.create(AppError.STORAGE_OPEN, {
|
||||
throw ERROR_FACTORY.create(AppError.IDB_OPEN, {
|
||||
originalErrorMessage: e.message
|
||||
});
|
||||
});
|
||||
@@ -65,9 +67,14 @@ export async function readHeartbeatsFromIndexedDB(
|
||||
.objectStore(STORE_NAME)
|
||||
.get(computeKey(app)) as Promise<HeartbeatsInIndexedDB | undefined>;
|
||||
} catch (e) {
|
||||
throw ERROR_FACTORY.create(AppError.STORAGE_GET, {
|
||||
originalErrorMessage: (e as Error)?.message
|
||||
});
|
||||
if (e instanceof FirebaseError) {
|
||||
logger.warn(e.message);
|
||||
} else {
|
||||
const idbGetError = ERROR_FACTORY.create(AppError.IDB_GET, {
|
||||
originalErrorMessage: (e as Error)?.message
|
||||
});
|
||||
logger.warn(idbGetError.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,9 +89,14 @@ export async function writeHeartbeatsToIndexedDB(
|
||||
await objectStore.put(heartbeatObject, computeKey(app));
|
||||
return tx.done;
|
||||
} catch (e) {
|
||||
throw ERROR_FACTORY.create(AppError.STORAGE_WRITE, {
|
||||
originalErrorMessage: (e as Error)?.message
|
||||
});
|
||||
if (e instanceof FirebaseError) {
|
||||
logger.warn(e.message);
|
||||
} else {
|
||||
const idbGetError = ERROR_FACTORY.create(AppError.IDB_WRITE, {
|
||||
originalErrorMessage: (e as Error)?.message
|
||||
});
|
||||
logger.warn(idbGetError.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user