/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { CommonModule, DOCUMENT, XhrFactory, ɵPLATFORM_BROWSER_ID as PLATFORM_BROWSER_ID, } from '@angular/common'; import { APP_ID, ApplicationConfig as ApplicationConfigFromCore, ApplicationModule, ApplicationRef, createPlatformFactory, ErrorHandler, Inject, InjectionToken, ModuleWithProviders, NgModule, NgZone, Optional, PLATFORM_ID, PLATFORM_INITIALIZER, platformCore, PlatformRef, Provider, RendererFactory2, SkipSelf, StaticProvider, Testability, TestabilityRegistry, Type, ɵINJECTOR_SCOPE as INJECTOR_SCOPE, ɵinternalCreateApplication as internalCreateApplication, ɵRuntimeError as RuntimeError, ɵsetDocument, ɵTESTABILITY as TESTABILITY, ɵTESTABILITY_GETTER as TESTABILITY_GETTER, } from '@angular/core'; import {BrowserDomAdapter} from './browser/browser_adapter'; import {BrowserGetTestability} from './browser/testability'; import {BrowserXhr} from './browser/xhr'; import {DomRendererFactory2} from './dom/dom_renderer'; import {DomEventsPlugin} from './dom/events/dom_events'; import {EventDelegationPlugin} from './dom/events/event_delegation'; import {EVENT_MANAGER_PLUGINS, EventManager} from './dom/events/event_manager'; import {KeyEventsPlugin} from './dom/events/key_events'; import {SharedStylesHost} from './dom/shared_styles_host'; import {RuntimeErrorCode} from './errors'; /** * Set of config options available during the application bootstrap operation. * * @publicApi * * @deprecated * `ApplicationConfig` has moved, please import `ApplicationConfig` from `@angular/core` instead. */ // The below is a workaround to add a deprecated message. type ApplicationConfig = ApplicationConfigFromCore; export {ApplicationConfig}; /** * Bootstraps an instance of an Angular application and renders a standalone component as the * application's root component. More information about standalone components can be found in [this * guide](guide/components/importing). * * @usageNotes * The root component passed into this function *must* be a standalone one (should have the * `standalone: true` flag in the `@Component` decorator config). * * ```typescript * @Component({ * standalone: true, * template: 'Hello world!' * }) * class RootComponent {} * * const appRef: ApplicationRef = await bootstrapApplication(RootComponent); * ``` * * You can add the list of providers that should be available in the application injector by * specifying the `providers` field in an object passed as the second argument: * * ```typescript * await bootstrapApplication(RootComponent, { * providers: [ * {provide: BACKEND_URL, useValue: 'https://yourdomain.com/api'} * ] * }); * ``` * * The `importProvidersFrom` helper method can be used to collect all providers from any * existing NgModule (and transitively from all NgModules that it imports): * * ```typescript * await bootstrapApplication(RootComponent, { * providers: [ * importProvidersFrom(SomeNgModule) * ] * }); * ``` * * Note: the `bootstrapApplication` method doesn't include [Testability](api/core/Testability) by * default. You can add [Testability](api/core/Testability) by getting the list of necessary * providers using `provideProtractorTestingSupport()` function and adding them into the `providers` * array, for example: * * ```typescript * import {provideProtractorTestingSupport} from '@angular/platform-browser'; * * await bootstrapApplication(RootComponent, {providers: [provideProtractorTestingSupport()]}); * ``` * * @param rootComponent A reference to a standalone component that should be rendered. * @param options Extra configuration for the bootstrap operation, see `ApplicationConfig` for * additional info. * @returns A promise that returns an `ApplicationRef` instance once resolved. * * @publicApi */ export function bootstrapApplication( rootComponent: Type, options?: ApplicationConfig, ): Promise { return internalCreateApplication({rootComponent, ...createProvidersConfig(options)}); } /** * Create an instance of an Angular application without bootstrapping any components. This is useful * for the situation where one wants to decouple application environment creation (a platform and * associated injectors) from rendering components on a screen. Components can be subsequently * bootstrapped on the returned `ApplicationRef`. * * @param options Extra configuration for the application environment, see `ApplicationConfig` for * additional info. * @returns A promise that returns an `ApplicationRef` instance once resolved. * * @publicApi */ export function createApplication(options?: ApplicationConfig) { return internalCreateApplication(createProvidersConfig(options)); } function createProvidersConfig(options?: ApplicationConfig) { return { appProviders: [...BROWSER_MODULE_PROVIDERS, ...(options?.providers ?? [])], platformProviders: INTERNAL_BROWSER_PLATFORM_PROVIDERS, }; } /** * Returns a set of providers required to setup [Testability](api/core/Testability) for an * application bootstrapped using the `bootstrapApplication` function. The set of providers is * needed to support testing an application with Protractor (which relies on the Testability APIs * to be present). * * @returns An array of providers required to setup Testability for an application and make it * available for testing using Protractor. * * @publicApi */ export function provideProtractorTestingSupport(): Provider[] { // Return a copy to prevent changes to the original array in case any in-place // alterations are performed to the `provideProtractorTestingSupport` call results in app // code. return [...TESTABILITY_PROVIDERS]; } export function initDomAdapter() { BrowserDomAdapter.makeCurrent(); } export function errorHandler(): ErrorHandler { return new ErrorHandler(); } export function _document(): any { // Tell ivy about the global document ɵsetDocument(document); return document; } export const INTERNAL_BROWSER_PLATFORM_PROVIDERS: StaticProvider[] = [ {provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID}, {provide: PLATFORM_INITIALIZER, useValue: initDomAdapter, multi: true}, {provide: DOCUMENT, useFactory: _document, deps: []}, ]; /** * A factory function that returns a `PlatformRef` instance associated with browser service * providers. * * @publicApi */ export const platformBrowser: (extraProviders?: StaticProvider[]) => PlatformRef = createPlatformFactory(platformCore, 'browser', INTERNAL_BROWSER_PLATFORM_PROVIDERS); /** * Internal marker to signal whether providers from the `BrowserModule` are already present in DI. * This is needed to avoid loading `BrowserModule` providers twice. We can't rely on the * `BrowserModule` presence itself, since the standalone-based bootstrap just imports * `BrowserModule` providers without referencing the module itself. */ const BROWSER_MODULE_PROVIDERS_MARKER = new InjectionToken( typeof ngDevMode === 'undefined' || ngDevMode ? 'BrowserModule Providers Marker' : '', ); const TESTABILITY_PROVIDERS = [ { provide: TESTABILITY_GETTER, useClass: BrowserGetTestability, deps: [], }, { provide: TESTABILITY, useClass: Testability, deps: [NgZone, TestabilityRegistry, TESTABILITY_GETTER], }, { provide: Testability, // Also provide as `Testability` for backwards-compatibility. useClass: Testability, deps: [NgZone, TestabilityRegistry, TESTABILITY_GETTER], }, ]; const BROWSER_MODULE_PROVIDERS: Provider[] = [ {provide: INJECTOR_SCOPE, useValue: 'root'}, {provide: ErrorHandler, useFactory: errorHandler, deps: []}, { provide: EVENT_MANAGER_PLUGINS, useClass: DomEventsPlugin, multi: true, deps: [DOCUMENT, NgZone, PLATFORM_ID], }, {provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true, deps: [DOCUMENT]}, { provide: EVENT_MANAGER_PLUGINS, useClass: EventDelegationPlugin, multi: true, }, DomRendererFactory2, SharedStylesHost, EventManager, {provide: RendererFactory2, useExisting: DomRendererFactory2}, {provide: XhrFactory, useClass: BrowserXhr, deps: []}, typeof ngDevMode === 'undefined' || ngDevMode ? {provide: BROWSER_MODULE_PROVIDERS_MARKER, useValue: true} : [], ]; /** * Exports required infrastructure for all Angular apps. * Included by default in all Angular apps created with the CLI * `new` command. * Re-exports `CommonModule` and `ApplicationModule`, making their * exports and providers available to all apps. * * @publicApi */ @NgModule({ providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS], exports: [CommonModule, ApplicationModule], }) export class BrowserModule { constructor( @Optional() @SkipSelf() @Inject(BROWSER_MODULE_PROVIDERS_MARKER) providersAlreadyPresent: boolean | null, ) { if ((typeof ngDevMode === 'undefined' || ngDevMode) && providersAlreadyPresent) { throw new RuntimeError( RuntimeErrorCode.BROWSER_MODULE_ALREADY_LOADED, `Providers from the \`BrowserModule\` have already been loaded. If you need access ` + `to common directives such as NgIf and NgFor, import the \`CommonModule\` instead.`, ); } } /** * Configures a browser-based app to transition from a server-rendered app, if * one is present on the page. * * @param params An object containing an identifier for the app to transition. * The ID must match between the client and server versions of the app. * @returns The reconfigured `BrowserModule` to import into the app's root `AppModule`. * * @deprecated Use {@link APP_ID} instead to set the application ID. */ static withServerTransition(params: {appId: string}): ModuleWithProviders { return { ngModule: BrowserModule, providers: [{provide: APP_ID, useValue: params.appId}], }; } }