From e0ad9ecda0b8a541b405d2ab35335b90ceb21fd1 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Fri, 17 Jan 2020 12:52:59 +0000 Subject: [PATCH] fix(ivy): ensure that `LOCALE_ID` is set after app initializers (#34830) Before ivy it was possible to configure a mutable service value in an application initializer (by providing an `APP_INITIALIZER`) that could be read in the provider of `LOCALE_ID`. This is a common scenario if you wanted to load the locale id asynchronously from an HTTP request for instance. When using the ivy, the runtime needs to be told what the current locale is, which is done by calling the `setLocaleId()` function with the value injected by the `LOCALE_ID` token. Previously this was being done before the application initializers were run, which meant that the `LOCALE_ID` provider was being executed before the app initializers had a chance to get a new value for it. Now this initalization of the locale for the ivy runtime is done after the application initializers have been run. Closes #34701 PR Close #34830 --- packages/core/src/application_ref.ts | 10 +++++----- packages/core/test/application_ref_spec.ts | 4 +--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/core/src/application_ref.ts b/packages/core/src/application_ref.ts index 91e4a40e80..24f173fdf6 100644 --- a/packages/core/src/application_ref.ts +++ b/packages/core/src/application_ref.ts @@ -302,11 +302,6 @@ export class PlatformRef { if (!exceptionHandler) { throw new Error('No ErrorHandler. Is platform module (BrowserModule) included?'); } - // If the `LOCALE_ID` provider is defined at bootstrap we set the value for runtime i18n (ivy) - if (ivyEnabled) { - const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID); - setLocaleId(localeId || DEFAULT_LOCALE_ID); - } moduleRef.onDestroy(() => remove(this._modules, moduleRef)); ngZone !.runOutsideAngular( () => ngZone !.onError.subscribe( @@ -315,6 +310,11 @@ export class PlatformRef { const initStatus: ApplicationInitStatus = moduleRef.injector.get(ApplicationInitStatus); initStatus.runInitializers(); return initStatus.donePromise.then(() => { + if (ivyEnabled) { + // If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy + const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID); + setLocaleId(localeId || DEFAULT_LOCALE_ID); + } this._moduleDoBootstrap(moduleRef); return moduleRef; }); diff --git a/packages/core/test/application_ref_spec.ts b/packages/core/test/application_ref_spec.ts index 54c4ae825d..8639cbe0db 100644 --- a/packages/core/test/application_ref_spec.ts +++ b/packages/core/test/application_ref_spec.ts @@ -346,11 +346,9 @@ class SomeComponent { it('should wait for APP_INITIALIZER to set providers for `LOCALE_ID`', async() => { let locale: string = ''; - const promise = Promise.resolve().then(() => { locale = 'fr-FR'; }); - const testModule = createModule({ providers: [ - {provide: APP_INITIALIZER, useValue: () => promise, multi: true}, + {provide: APP_INITIALIZER, useValue: () => locale = 'fr-FR', multi: true}, {provide: LOCALE_ID, useFactory: () => locale} ] });