diff --git a/packages/app/src/api.test.ts b/packages/app/src/api.test.ts index 7faabc1e1a7..9a4f1fbe216 100644 --- a/packages/app/src/api.test.ts +++ b/packages/app/src/api.test.ts @@ -40,6 +40,7 @@ import { createTestComponent } from '../test/util'; import { Component, ComponentType } from '@firebase/component'; import { Logger } from '@firebase/logger'; import { FirebaseAppImpl } from './firebaseApp'; +import { FirebaseServerAppImpl } from './firebaseServerApp'; import { isBrowser } from '@firebase/util'; declare module '@firebase/component' { @@ -184,7 +185,7 @@ describe('API tests', () => { }); describe('initializeServerApp', () => { - it('creates FirebaseServerApp with options', () => { + it('creates FirebaseServerApp fails in browsers.', () => { if (isBrowser()) { const options = { apiKey: 'APIKEY' @@ -196,7 +197,7 @@ describe('API tests', () => { } }); - it('creates FirebaseServerApp with options', () => { + it('creates FirebaseServerApp with options', async () => { if (isBrowser()) { // FirebaseServerApp isn't supported for execution in browser enviornments. return; @@ -211,9 +212,10 @@ describe('API tests', () => { const app = initializeServerApp(options, serverAppSettings); expect(app).to.not.equal(null); expect(app.automaticDataCollectionEnabled).to.be.false; + await deleteApp(app); }); - it('creates FirebaseServerApp with automaticDataCollectionEnabled', () => { + it('creates FirebaseServerApp with automaticDataCollectionEnabled', async () => { if (isBrowser()) { // FirebaseServerApp isn't supported for execution in browser enviornments. return; @@ -230,9 +232,10 @@ describe('API tests', () => { const app = initializeServerApp(options, serverAppSettings); expect(app).to.not.equal(null); expect(app.automaticDataCollectionEnabled).to.be.true; + await deleteApp(app); }); - it('creates FirebaseServerApp with releaseOnDeref', () => { + it('creates FirebaseServerApp with releaseOnDeref', async () => { if (isBrowser()) { // FirebaseServerApp isn't supported for execution in browser enviornments. return; @@ -247,9 +250,10 @@ describe('API tests', () => { const app = initializeServerApp(options, serverAppSettings); expect(app).to.not.equal(null); expect(app.automaticDataCollectionEnabled).to.be.false; + await deleteApp(app); }); - it('creates FirebaseServerApp with FirebaseApp', () => { + it('creates FirebaseServerApp with FirebaseApp', async () => { if (isBrowser()) { // FirebaseServerApp isn't supported for execution in browser enviornments. return; @@ -266,12 +270,65 @@ describe('API tests', () => { automaticDataCollectionEnabled: false }; - const serverApp = initializeServerApp(standardApp, serverAppSettings); - expect(serverApp).to.not.equal(null); - expect(serverApp.options.apiKey).to.equal('test1'); + const app = initializeServerApp(standardApp, serverAppSettings); + expect(app).to.not.equal(null); + expect(app.options.apiKey).to.equal('test1'); + await deleteApp(app); }); }); + it('create similar FirebaseServerApps does not return the same object', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser enviornments. + return; + } + + const options = { apiKey: 'APIKEY' }; + const serverAppSettingsOne: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const serverAppSettingsTwo: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false + }; + + const appOne = initializeServerApp(options, serverAppSettingsOne); + expect(appOne).to.not.equal(null); + expect(appOne.automaticDataCollectionEnabled).to.be.false; + const appTwo = initializeServerApp(options, serverAppSettingsTwo); + expect(appTwo).to.not.equal(null); + expect(appTwo).to.not.equal(appOne); + await deleteApp(appOne); + await deleteApp(appTwo); + }); + + it('create duplicate FirebaseServerApps returns the same object', async () => { + if (isBrowser()) { + // FirebaseServerApp isn't supported for execution in browser enviornments. + return; + } + + const options = { apiKey: 'APIKEY' }; + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + releaseOnDeref: options + }; + + const appOne = initializeServerApp(options, serverAppSettings); + expect(appOne).to.not.equal(null); + expect(appOne.automaticDataCollectionEnabled).to.be.false; + const appTwo = initializeServerApp(options, serverAppSettings); + expect(appTwo).to.not.equal(null); + expect(appTwo).to.equal(appOne); + await deleteApp(appOne); + + // TODO: When Reference Counting works, update test. The following line should be false + // until and the app should be deleted a second time. + expect((appOne as FirebaseServerAppImpl).isDeleted).to.be.true; + // await deleteApp(appTwo); + }); + describe('getApp', () => { it('retrieves DEFAULT App', () => { const app = initializeApp({}); diff --git a/packages/app/src/api.ts b/packages/app/src/api.ts index c8383d06fd9..246c06b144f 100644 --- a/packages/app/src/api.ts +++ b/packages/app/src/api.ts @@ -235,11 +235,6 @@ export function initializeServerApp( throw ERROR_FACTORY.create(AppError.INVALID_SERVER_APP_ENVIRONMENT); } - const serverAppSettings: FirebaseServerAppSettings = { - automaticDataCollectionEnabled: false, - ..._serverAppConfig - }; - let appOptions: FirebaseOptions; if (_isFirebaseApp(_options)) { appOptions = _options.options; @@ -247,10 +242,23 @@ export function initializeServerApp( appOptions = _options; } + // Mangle the ap name based on a hash of the FirebaseServerAppSettings, and FirebaseOptions + // objects and the authIdToken, if provided. const nameObj = { - authIdToken: _serverAppConfig?.authIdToken, + _serverAppConfig, ...appOptions }; + const hashCode = (s: string): number => { + return [...s].reduce( + (hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, + 0 + ); + }; + + const serverAppSettings: FirebaseServerAppSettings = { + automaticDataCollectionEnabled: false, + ..._serverAppConfig + }; if (serverAppSettings.releaseOnDeref !== undefined) { if (typeof FinalizationRegistry === 'undefined') { @@ -261,14 +269,6 @@ export function initializeServerApp( } } - // TODO: move this into util.js. - const hashCode = (s: string): number => { - return [...s].reduce( - (hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, - 0 - ); - }; - const nameString = '' + hashCode(JSON.stringify(nameObj)); const existingApp = _serverApps.get(nameString) as FirebaseServerApp; if (existingApp) { @@ -286,9 +286,12 @@ export function initializeServerApp( const newApp = new FirebaseServerAppImpl( appOptions, serverAppSettings, + nameString, container ); + _serverApps.set(nameString, newApp); + return newApp; } diff --git a/packages/app/src/firebaseServerApp.test.ts b/packages/app/src/firebaseServerApp.test.ts index a95f7e42d8a..c31d603b0e1 100644 --- a/packages/app/src/firebaseServerApp.test.ts +++ b/packages/app/src/firebaseServerApp.test.ts @@ -35,6 +35,7 @@ describe('FirebaseServerApp', () => { const firebaseServerAppImpl = new FirebaseServerAppImpl( options, serverAppSettings, + 'testName', new ComponentContainer('test') ); @@ -55,6 +56,7 @@ describe('FirebaseServerApp', () => { const firebaseServerAppImpl = new FirebaseServerAppImpl( options, serverAppSettings, + 'testName', new ComponentContainer('test') ); @@ -75,6 +77,7 @@ describe('FirebaseServerApp', () => { const firebaseServerAppImpl = new FirebaseServerAppImpl( options, serverAppSettings, + 'testName', new ComponentContainer('test') ); @@ -96,6 +99,7 @@ describe('FirebaseServerApp', () => { const app = new FirebaseServerAppImpl( options, serverAppSettings, + 'testName', new ComponentContainer('test') ); @@ -122,6 +126,7 @@ describe('FirebaseServerApp', () => { const app = new FirebaseServerAppImpl( options, serverAppSettings, + 'testName', new ComponentContainer('test') ); @@ -131,13 +136,5 @@ describe('FirebaseServerApp', () => { expect(() => app.authIdTokenVerified()).throws( 'Firebase Server App has been deleted' ); - - expect(() => app.appCheckTokenVerified()).throws( - 'Firebase Server App has been deleted' - ); - - expect(() => app.installationTokenVerified()).throws( - 'Firebase Server App has been deleted' - ); }); }); diff --git a/packages/app/src/firebaseServerApp.ts b/packages/app/src/firebaseServerApp.ts index 7c51511d087..0135ff8897a 100644 --- a/packages/app/src/firebaseServerApp.ts +++ b/packages/app/src/firebaseServerApp.ts @@ -36,6 +36,7 @@ export class FirebaseServerAppImpl constructor( options: FirebaseOptions | FirebaseAppImpl, serverConfig: FirebaseServerAppSettings, + name: string, container: ComponentContainer ) { // Build configuration parameters for the FirebaseAppImpl base class. @@ -46,7 +47,7 @@ export class FirebaseServerAppImpl // Create the FirebaseAppSettings object for the FirebaseAppImp constructor. const config: Required = { - name: '', + name, automaticDataCollectionEnabled }; @@ -55,7 +56,6 @@ export class FirebaseServerAppImpl super(options as FirebaseOptions, config, container); } else { const appImpl: FirebaseAppImpl = options as FirebaseAppImpl; - super(appImpl.options, config, container); } @@ -94,18 +94,6 @@ export class FirebaseServerAppImpl return Promise.resolve(); } - appCheckTokenVerified(): Promise { - this.checkDestroyed(); - // TODO - return Promise.resolve(); - } - - installationTokenVerified(): Promise { - this.checkDestroyed(); - // TODO - return Promise.resolve(); - } - /** * This function will throw an Error if the App has already been deleted - * use before performing API actions on the App.