@@ -18,6 +18,7 @@ import { Auth } from '../../model/public_types';
1818import  {  AuthErrorCode  }  from  '../errors' ; 
1919import  {  _assert  }  from  '../util/assert' ; 
2020import  {  _castAuth  }  from  './auth_impl' ; 
21+ import  {  deepEqual  }  from  '@firebase/util' ; 
2122
2223/** 
2324 * Changes the {@link  Auth} instance to communicate with the Firebase Auth Emulator, instead of production 
@@ -47,12 +48,6 @@ export function connectAuthEmulator(
4748  options ?: {  disableWarnings : boolean  } 
4849) : void { 
4950  const  authInternal  =  _castAuth ( auth ) ; 
50-   _assert ( 
51-     authInternal . _canInitEmulator , 
52-     authInternal , 
53-     AuthErrorCode . EMULATOR_CONFIG_FAILED 
54-   ) ; 
55- 
5651  _assert ( 
5752    / ^ h t t p s ? : \/ \/ / . test ( url ) , 
5853    authInternal , 
@@ -66,15 +61,42 @@ export function connectAuthEmulator(
6661  const  portStr  =  port  ===  null  ? ''  : `:${ port }  ; 
6762
6863  // Always replace path with "/" (even if input url had no path at all, or had a different one). 
69-   authInternal . config . emulator  =  {  url : `${ protocol } ${ host } ${ portStr }   } ; 
70-   authInternal . settings . appVerificationDisabledForTesting  =  true ; 
71-   authInternal . emulatorConfig  =  Object . freeze ( { 
64+   const  emulator  =  {  url : `${ protocol } ${ host } ${ portStr }   } ; 
65+   const  emulatorConfig  =  Object . freeze ( { 
7266    host, 
7367    port, 
7468    protocol : protocol . replace ( ':' ,  '' ) , 
7569    options : Object . freeze ( {  disableWarnings } ) 
7670  } ) ; 
7771
72+   // There are a few scenarios to guard against if the Auth instance has already started: 
73+   if  ( ! authInternal . _canInitEmulator )  { 
74+     // Applications may not initialize the emulator for the first time if Auth has already started 
75+     // to make network requests. 
76+     _assert ( 
77+       authInternal . config . emulator  &&  authInternal . emulatorConfig , 
78+       authInternal , 
79+       AuthErrorCode . EMULATOR_CONFIG_FAILED 
80+     ) ; 
81+ 
82+     // Applications may not alter the configuration of the emulator (aka pass a different config) 
83+     // once Auth has started to make network requests. 
84+     _assert ( 
85+       deepEqual ( emulator ,  authInternal . config . emulator )  && 
86+         deepEqual ( emulatorConfig ,  authInternal . emulatorConfig ) , 
87+       authInternal , 
88+       AuthErrorCode . EMULATOR_CONFIG_FAILED 
89+     ) ; 
90+ 
91+     // It's valid, however, to invoke connectAuthEmulator() after Auth has started making 
92+     // connections, so long as the config matches the existing config. This results in a no-op. 
93+     return ; 
94+   } 
95+ 
96+   authInternal . config . emulator  =  emulator ; 
97+   authInternal . emulatorConfig  =  emulatorConfig ; 
98+   authInternal . settings . appVerificationDisabledForTesting  =  true ; 
99+ 
78100  if  ( ! disableWarnings )  { 
79101    emitEmulatorWarning ( ) ; 
80102  } 
0 commit comments