@angular/core
Version:
Angular - the core framework
897 lines • 123 kB
JavaScript
/**
* @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 './util/ng_jit_mode';
import { merge, Observable } from 'rxjs';
import { share } from 'rxjs/operators';
import { ApplicationInitStatus } from './application_init';
import { APP_BOOTSTRAP_LISTENER, PLATFORM_INITIALIZER } from './application_tokens';
import { getCompilerFacade } from './compiler/compiler_facade';
import { Console } from './console';
import { Injectable } from './di/injectable';
import { InjectionToken } from './di/injection_token';
import { Injector } from './di/injector';
import { EnvironmentInjector } from './di/r3_injector';
import { INJECTOR_SCOPE } from './di/scope';
import { ErrorHandler } from './error_handler';
import { formatRuntimeError, RuntimeError } from './errors';
import { DEFAULT_LOCALE_ID } from './i18n/localization';
import { LOCALE_ID } from './i18n/tokens';
import { COMPILER_OPTIONS } from './linker/compiler';
import { ComponentFactory } from './linker/component_factory';
import { ComponentFactoryResolver } from './linker/component_factory_resolver';
import { NgModuleRef } from './linker/ng_module_factory';
import { isComponentResourceResolutionQueueEmpty, resolveComponentResources } from './metadata/resource_loading';
import { assertNgModuleType } from './render3/assert';
import { isStandalone } from './render3/definition';
import { assertStandaloneComponentType } from './render3/errors';
import { setLocaleId } from './render3/i18n/i18n_locale_id';
import { setJitOptions } from './render3/jit/jit_options';
import { createEnvironmentInjector, NgModuleFactory as R3NgModuleFactory } from './render3/ng_module_ref';
import { publishDefaultGlobalUtils as _publishDefaultGlobalUtils } from './render3/util/global_utils';
import { TESTABILITY } from './testability/testability';
import { isPromise } from './util/lang';
import { scheduleMicroTask } from './util/microtask';
import { stringify } from './util/stringify';
import { NgZone, NoopNgZone } from './zone/ng_zone';
import * as i0 from "./r3_symbols";
import * as i1 from "./di/injector";
import * as i2 from "./zone/ng_zone";
import * as i3 from "./di/r3_injector";
import * as i4 from "./error_handler";
let _platformInjector = null;
/**
* Internal token to indicate whether having multiple bootstrapped platform should be allowed (only
* one bootstrapped platform is allowed by default). This token helps to support SSR scenarios.
*/
export const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken('AllowMultipleToken');
/**
* Internal token that allows to register extra callbacks that should be invoked during the
* `PlatformRef.destroy` operation. This token is needed to avoid a direct reference to the
* `PlatformRef` class (i.e. register the callback via `PlatformRef.onDestroy`), thus making the
* entire class tree-shakeable.
*/
const PLATFORM_DESTROY_LISTENERS = new InjectionToken('PlatformDestroyListeners');
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
export function compileNgModuleFactory(injector, options, moduleType) {
ngDevMode && assertNgModuleType(moduleType);
const moduleFactory = new R3NgModuleFactory(moduleType);
// All of the logic below is irrelevant for AOT-compiled code.
if (typeof ngJitMode !== 'undefined' && !ngJitMode) {
return Promise.resolve(moduleFactory);
}
const compilerOptions = injector.get(COMPILER_OPTIONS, []).concat(options);
// Configure the compiler to use the provided options. This call may fail when multiple modules
// are bootstrapped with incompatible options, as a component can only be compiled according to
// a single set of options.
setJitOptions({
defaultEncapsulation: _lastDefined(compilerOptions.map(opts => opts.defaultEncapsulation)),
preserveWhitespaces: _lastDefined(compilerOptions.map(opts => opts.preserveWhitespaces)),
});
if (isComponentResourceResolutionQueueEmpty()) {
return Promise.resolve(moduleFactory);
}
const compilerProviders = _mergeArrays(compilerOptions.map(o => o.providers));
// In case there are no compiler providers, we just return the module factory as
// there won't be any resource loader. This can happen with Ivy, because AOT compiled
// modules can be still passed through "bootstrapModule". In that case we shouldn't
// unnecessarily require the JIT compiler.
if (compilerProviders.length === 0) {
return Promise.resolve(moduleFactory);
}
const compiler = getCompilerFacade({
usage: 0 /* JitCompilerUsage.Decorator */,
kind: 'NgModule',
type: moduleType,
});
const compilerInjector = Injector.create({ providers: compilerProviders });
const resourceLoader = compilerInjector.get(compiler.ResourceLoader);
// The resource loader can also return a string while the "resolveComponentResources"
// always expects a promise. Therefore we need to wrap the returned value in a promise.
return resolveComponentResources(url => Promise.resolve(resourceLoader.get(url)))
.then(() => moduleFactory);
}
export function publishDefaultGlobalUtils() {
ngDevMode && _publishDefaultGlobalUtils();
}
export function isBoundToModule(cf) {
return cf.isBoundToModule;
}
/**
* A token for third-party components that can register themselves with NgProbe.
*
* @publicApi
*/
export class NgProbeToken {
constructor(name, token) {
this.name = name;
this.token = token;
}
}
/**
* Creates a platform.
* Platforms must be created on launch using this function.
*
* @publicApi
*/
export function createPlatform(injector) {
if (_platformInjector && !_platformInjector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
throw new RuntimeError(400 /* RuntimeErrorCode.MULTIPLE_PLATFORMS */, ngDevMode &&
'There can be only one platform. Destroy the previous one to create a new one.');
}
publishDefaultGlobalUtils();
_platformInjector = injector;
const platform = injector.get(PlatformRef);
runPlatformInitializers(injector);
return platform;
}
/**
* The goal of this function is to bootstrap a platform injector,
* but avoid referencing `PlatformRef` class.
* This function is needed for bootstrapping a Standalone Component.
*/
export function createOrReusePlatformInjector(providers = []) {
// If a platform injector already exists, it means that the platform
// is already bootstrapped and no additional actions are required.
if (_platformInjector)
return _platformInjector;
// Otherwise, setup a new platform injector and run platform initializers.
const injector = createPlatformInjector(providers);
_platformInjector = injector;
publishDefaultGlobalUtils();
runPlatformInitializers(injector);
return injector;
}
export function runPlatformInitializers(injector) {
const inits = injector.get(PLATFORM_INITIALIZER, null);
if (inits) {
inits.forEach((init) => init());
}
}
/**
* Internal create application API that implements the core application creation logic and optional
* bootstrap logic.
*
* Platforms (such as `platform-browser`) may require different set of application and platform
* providers for an application to function correctly. As a result, platforms may use this function
* internally and supply the necessary providers during the bootstrap, while exposing
* platform-specific APIs as a part of their public API.
*
* @returns A promise that returns an `ApplicationRef` instance once resolved.
*/
export function internalCreateApplication(config) {
const { rootComponent, appProviders, platformProviders } = config;
if (NG_DEV_MODE && rootComponent !== undefined) {
assertStandaloneComponentType(rootComponent);
}
const platformInjector = createOrReusePlatformInjector(platformProviders);
const ngZone = getNgZone('zone.js', getNgZoneOptions());
return ngZone.run(() => {
// Create root application injector based on a set of providers configured at the platform
// bootstrap level as well as providers passed to the bootstrap call by a user.
const allAppProviders = [
{ provide: NgZone, useValue: ngZone },
...(appProviders || []), //
];
const envInjector = createEnvironmentInjector(allAppProviders, platformInjector, 'Environment Injector');
const exceptionHandler = envInjector.get(ErrorHandler, null);
if (NG_DEV_MODE && !exceptionHandler) {
throw new RuntimeError(402 /* RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND */, 'No `ErrorHandler` found in the Dependency Injection tree.');
}
let onErrorSubscription;
ngZone.runOutsideAngular(() => {
onErrorSubscription = ngZone.onError.subscribe({
next: (error) => {
exceptionHandler.handleError(error);
}
});
});
// If the whole platform is destroyed, invoke the `destroy` method
// for all bootstrapped applications as well.
const destroyListener = () => envInjector.destroy();
const onPlatformDestroyListeners = platformInjector.get(PLATFORM_DESTROY_LISTENERS);
onPlatformDestroyListeners.add(destroyListener);
envInjector.onDestroy(() => {
onErrorSubscription.unsubscribe();
onPlatformDestroyListeners.delete(destroyListener);
});
return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
const initStatus = envInjector.get(ApplicationInitStatus);
initStatus.runInitializers();
return initStatus.donePromise.then(() => {
const localeId = envInjector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
setLocaleId(localeId || DEFAULT_LOCALE_ID);
const appRef = envInjector.get(ApplicationRef);
if (rootComponent !== undefined) {
appRef.bootstrap(rootComponent);
}
return appRef;
});
});
});
}
/**
* Creates a factory for a platform. Can be used to provide or override `Providers` specific to
* your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.
* @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories
* to build up configurations that might be required by different libraries or parts of the
* application.
* @param name Identifies the new platform factory.
* @param providers A set of dependency providers for platforms created with the new factory.
*
* @publicApi
*/
export function createPlatformFactory(parentPlatformFactory, name, providers = []) {
const desc = `Platform: ${name}`;
const marker = new InjectionToken(desc);
return (extraProviders = []) => {
let platform = getPlatform();
if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
const platformProviders = [
...providers,
...extraProviders,
{ provide: marker, useValue: true }
];
if (parentPlatformFactory) {
parentPlatformFactory(platformProviders);
}
else {
createPlatform(createPlatformInjector(platformProviders, desc));
}
}
return assertPlatform(marker);
};
}
/**
* Checks that there is currently a platform that contains the given token as a provider.
*
* @publicApi
*/
export function assertPlatform(requiredToken) {
const platform = getPlatform();
if (!platform) {
throw new RuntimeError(401 /* RuntimeErrorCode.PLATFORM_NOT_FOUND */, ngDevMode && 'No platform exists!');
}
if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
!platform.injector.get(requiredToken, null)) {
throw new RuntimeError(400 /* RuntimeErrorCode.MULTIPLE_PLATFORMS */, 'A platform with a different configuration has been created. Please destroy it first.');
}
return platform;
}
/**
* Helper function to create an instance of a platform injector (that maintains the 'platform'
* scope).
*/
export function createPlatformInjector(providers = [], name) {
return Injector.create({
name,
providers: [
{ provide: INJECTOR_SCOPE, useValue: 'platform' },
{ provide: PLATFORM_DESTROY_LISTENERS, useValue: new Set([() => _platformInjector = null]) },
...providers
],
});
}
/**
* Destroys the current Angular platform and all Angular applications on the page.
* Destroys all modules and listeners registered with the platform.
*
* @publicApi
*/
export function destroyPlatform() {
getPlatform()?.destroy();
}
/**
* Returns the current platform.
*
* @publicApi
*/
export function getPlatform() {
return _platformInjector?.get(PlatformRef) ?? null;
}
/**
* The Angular platform is the entry point for Angular on a web page.
* Each page has exactly one platform. Services (such as reflection) which are common
* to every Angular application running on the page are bound in its scope.
* A page's platform is initialized implicitly when a platform is created using a platform
* factory such as `PlatformBrowser`, or explicitly by calling the `createPlatform()` function.
*
* @publicApi
*/
export class PlatformRef {
/** @internal */
constructor(_injector) {
this._injector = _injector;
this._modules = [];
this._destroyListeners = [];
this._destroyed = false;
}
/**
* Creates an instance of an `@NgModule` for the given platform.
*
* @deprecated Passing NgModule factories as the `PlatformRef.bootstrapModuleFactory` function
* argument is deprecated. Use the `PlatformRef.bootstrapModule` API instead.
*/
bootstrapModuleFactory(moduleFactory, options) {
// Note: We need to create the NgZone _before_ we instantiate the module,
// as instantiating the module creates some providers eagerly.
// So we create a mini parent injector that just contains the new NgZone and
// pass that as parent to the NgModuleFactory.
const ngZone = getNgZone(options?.ngZone, getNgZoneOptions(options));
const providers = [{ provide: NgZone, useValue: ngZone }];
// Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are
// created within the Angular zone
// Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be
// created outside of the Angular zone.
return ngZone.run(() => {
const ngZoneInjector = Injector.create({ providers: providers, parent: this.injector, name: moduleFactory.moduleType.name });
const moduleRef = moduleFactory.create(ngZoneInjector);
const exceptionHandler = moduleRef.injector.get(ErrorHandler, null);
if (!exceptionHandler) {
throw new RuntimeError(402 /* RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND */, ngDevMode && 'No ErrorHandler. Is platform module (BrowserModule) included?');
}
ngZone.runOutsideAngular(() => {
const subscription = ngZone.onError.subscribe({
next: (error) => {
exceptionHandler.handleError(error);
}
});
moduleRef.onDestroy(() => {
remove(this._modules, moduleRef);
subscription.unsubscribe();
});
});
return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
const initStatus = moduleRef.injector.get(ApplicationInitStatus);
initStatus.runInitializers();
return initStatus.donePromise.then(() => {
// 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;
});
});
});
}
/**
* Creates an instance of an `@NgModule` for a given platform.
*
* @usageNotes
* ### Simple Example
*
* ```typescript
* @NgModule({
* imports: [BrowserModule]
* })
* class MyModule {}
*
* let moduleRef = platformBrowser().bootstrapModule(MyModule);
* ```
*
*/
bootstrapModule(moduleType, compilerOptions = []) {
const options = optionsReducer({}, compilerOptions);
return compileNgModuleFactory(this.injector, options, moduleType)
.then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));
}
_moduleDoBootstrap(moduleRef) {
const appRef = moduleRef.injector.get(ApplicationRef);
if (moduleRef._bootstrapComponents.length > 0) {
moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));
}
else if (moduleRef.instance.ngDoBootstrap) {
moduleRef.instance.ngDoBootstrap(appRef);
}
else {
throw new RuntimeError(-403 /* RuntimeErrorCode.BOOTSTRAP_COMPONENTS_NOT_FOUND */, ngDevMode &&
`The module ${stringify(moduleRef.instance.constructor)} was bootstrapped, ` +
`but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` +
`Please define one of these.`);
}
this._modules.push(moduleRef);
}
/**
* Registers a listener to be called when the platform is destroyed.
*/
onDestroy(callback) {
this._destroyListeners.push(callback);
}
/**
* Retrieves the platform {@link Injector}, which is the parent injector for
* every Angular application on the page and provides singleton providers.
*/
get injector() {
return this._injector;
}
/**
* Destroys the current Angular platform and all Angular applications on the page.
* Destroys all modules and listeners registered with the platform.
*/
destroy() {
if (this._destroyed) {
throw new RuntimeError(404 /* RuntimeErrorCode.PLATFORM_ALREADY_DESTROYED */, ngDevMode && 'The platform has already been destroyed!');
}
this._modules.slice().forEach(module => module.destroy());
this._destroyListeners.forEach(listener => listener());
const destroyListeners = this._injector.get(PLATFORM_DESTROY_LISTENERS, null);
if (destroyListeners) {
destroyListeners.forEach(listener => listener());
destroyListeners.clear();
}
this._destroyed = true;
}
/**
* Indicates whether this instance was destroyed.
*/
get destroyed() {
return this._destroyed;
}
}
PlatformRef.ɵfac = function PlatformRef_Factory(t) { return new (t || PlatformRef)(i0.ɵɵinject(i1.Injector)); };
PlatformRef.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PlatformRef, factory: PlatformRef.ɵfac, providedIn: 'platform' });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.setClassMetadata(PlatformRef, [{
type: Injectable,
args: [{ providedIn: 'platform' }]
}], function () { return [{ type: i1.Injector }]; }, null); })();
// Transforms a set of `BootstrapOptions` (supported by the NgModule-based bootstrap APIs) ->
// `NgZoneOptions` that are recognized by the NgZone constructor. Passing no options will result in
// a set of default options returned.
function getNgZoneOptions(options) {
return {
enableLongStackTrace: typeof ngDevMode === 'undefined' ? false : !!ngDevMode,
shouldCoalesceEventChangeDetection: !!(options && options.ngZoneEventCoalescing) || false,
shouldCoalesceRunChangeDetection: !!(options && options.ngZoneRunCoalescing) || false,
};
}
function getNgZone(ngZoneToUse, options) {
let ngZone;
if (ngZoneToUse === 'noop') {
ngZone = new NoopNgZone();
}
else {
ngZone = (ngZoneToUse === 'zone.js' ? undefined : ngZoneToUse) || new NgZone(options);
}
return ngZone;
}
function _callAndReportToErrorHandler(errorHandler, ngZone, callback) {
try {
const result = callback();
if (isPromise(result)) {
return result.catch((e) => {
ngZone.runOutsideAngular(() => errorHandler.handleError(e));
// rethrow as the exception handler might not do it
throw e;
});
}
return result;
}
catch (e) {
ngZone.runOutsideAngular(() => errorHandler.handleError(e));
// rethrow as the exception handler might not do it
throw e;
}
}
function optionsReducer(dst, objs) {
if (Array.isArray(objs)) {
dst = objs.reduce(optionsReducer, dst);
}
else {
dst = { ...dst, ...objs };
}
return dst;
}
/**
* A reference to an Angular application running on a page.
*
* @usageNotes
*
* {@a is-stable-examples}
* ### isStable examples and caveats
*
* Note two important points about `isStable`, demonstrated in the examples below:
* - the application will never be stable if you start any kind
* of recurrent asynchronous task when the application starts
* (for example for a polling process, started with a `setInterval`, a `setTimeout`
* or using RxJS operators like `interval`);
* - the `isStable` Observable runs outside of the Angular zone.
*
* Let's imagine that you start a recurrent task
* (here incrementing a counter, using RxJS `interval`),
* and at the same time subscribe to `isStable`.
*
* ```
* constructor(appRef: ApplicationRef) {
* appRef.isStable.pipe(
* filter(stable => stable)
* ).subscribe(() => console.log('App is stable now');
* interval(1000).subscribe(counter => console.log(counter));
* }
* ```
* In this example, `isStable` will never emit `true`,
* and the trace "App is stable now" will never get logged.
*
* If you want to execute something when the app is stable,
* you have to wait for the application to be stable
* before starting your polling process.
*
* ```
* constructor(appRef: ApplicationRef) {
* appRef.isStable.pipe(
* first(stable => stable),
* tap(stable => console.log('App is stable now')),
* switchMap(() => interval(1000))
* ).subscribe(counter => console.log(counter));
* }
* ```
* In this example, the trace "App is stable now" will be logged
* and then the counter starts incrementing every second.
*
* Note also that this Observable runs outside of the Angular zone,
* which means that the code in the subscription
* to this Observable will not trigger the change detection.
*
* Let's imagine that instead of logging the counter value,
* you update a field of your component
* and display it in its template.
*
* ```
* constructor(appRef: ApplicationRef) {
* appRef.isStable.pipe(
* first(stable => stable),
* switchMap(() => interval(1000))
* ).subscribe(counter => this.value = counter);
* }
* ```
* As the `isStable` Observable runs outside the zone,
* the `value` field will be updated properly,
* but the template will not be refreshed!
*
* You'll have to manually trigger the change detection to update the template.
*
* ```
* constructor(appRef: ApplicationRef, cd: ChangeDetectorRef) {
* appRef.isStable.pipe(
* first(stable => stable),
* switchMap(() => interval(1000))
* ).subscribe(counter => {
* this.value = counter;
* cd.detectChanges();
* });
* }
* ```
*
* Or make the subscription callback run inside the zone.
*
* ```
* constructor(appRef: ApplicationRef, zone: NgZone) {
* appRef.isStable.pipe(
* first(stable => stable),
* switchMap(() => interval(1000))
* ).subscribe(counter => zone.run(() => this.value = counter));
* }
* ```
*
* @publicApi
*/
export class ApplicationRef {
/**
* Indicates whether this instance was destroyed.
*/
get destroyed() {
return this._destroyed;
}
/**
* The `EnvironmentInjector` used to create this application.
*/
get injector() {
return this._injector;
}
/** @internal */
constructor(_zone, _injector, _exceptionHandler) {
this._zone = _zone;
this._injector = _injector;
this._exceptionHandler = _exceptionHandler;
/** @internal */
this._bootstrapListeners = [];
this._views = [];
this._runningTick = false;
this._stable = true;
this._destroyed = false;
this._destroyListeners = [];
/**
* Get a list of component types registered to this application.
* This list is populated even before the component is created.
*/
this.componentTypes = [];
/**
* Get a list of components registered to this application.
*/
this.components = [];
this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({
next: () => {
this._zone.run(() => {
this.tick();
});
}
});
const isCurrentlyStable = new Observable((observer) => {
this._stable = this._zone.isStable && !this._zone.hasPendingMacrotasks &&
!this._zone.hasPendingMicrotasks;
this._zone.runOutsideAngular(() => {
observer.next(this._stable);
observer.complete();
});
});
const isStable = new Observable((observer) => {
// Create the subscription to onStable outside the Angular Zone so that
// the callback is run outside the Angular Zone.
let stableSub;
this._zone.runOutsideAngular(() => {
stableSub = this._zone.onStable.subscribe(() => {
NgZone.assertNotInAngularZone();
// Check whether there are no pending macro/micro tasks in the next tick
// to allow for NgZone to update the state.
scheduleMicroTask(() => {
if (!this._stable && !this._zone.hasPendingMacrotasks &&
!this._zone.hasPendingMicrotasks) {
this._stable = true;
observer.next(true);
}
});
});
});
const unstableSub = this._zone.onUnstable.subscribe(() => {
NgZone.assertInAngularZone();
if (this._stable) {
this._stable = false;
this._zone.runOutsideAngular(() => {
observer.next(false);
});
}
});
return () => {
stableSub.unsubscribe();
unstableSub.unsubscribe();
};
});
this.isStable =
merge(isCurrentlyStable, isStable.pipe(share()));
}
/**
* Bootstrap a component onto the element identified by its selector or, optionally, to a
* specified element.
*
* @usageNotes
* ### Bootstrap process
*
* When bootstrapping a component, Angular mounts it onto a target DOM element
* and kicks off automatic change detection. The target DOM element can be
* provided using the `rootSelectorOrNode` argument.
*
* If the target DOM element is not provided, Angular tries to find one on a page
* using the `selector` of the component that is being bootstrapped
* (first matched element is used).
*
* ### Example
*
* Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`,
* but it requires us to know the component while writing the application code.
*
* Imagine a situation where we have to wait for an API call to decide about the component to
* bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to
* dynamically bootstrap a component.
*
* {@example core/ts/platform/platform.ts region='componentSelector'}
*
* Optionally, a component can be mounted onto a DOM element that does not match the
* selector of the bootstrapped component.
*
* In the following example, we are providing a CSS selector to match the target element.
*
* {@example core/ts/platform/platform.ts region='cssSelector'}
*
* While in this example, we are providing reference to a DOM node.
*
* {@example core/ts/platform/platform.ts region='domNode'}
*/
bootstrap(componentOrFactory, rootSelectorOrNode) {
NG_DEV_MODE && this.warnIfDestroyed();
const isComponentFactory = componentOrFactory instanceof ComponentFactory;
const initStatus = this._injector.get(ApplicationInitStatus);
if (!initStatus.done) {
const standalone = !isComponentFactory && isStandalone(componentOrFactory);
const errorMessage = 'Cannot bootstrap as there are still asynchronous initializers running.' +
(standalone ? '' :
' Bootstrap components in the `ngDoBootstrap` method of the root module.');
throw new RuntimeError(405 /* RuntimeErrorCode.ASYNC_INITIALIZERS_STILL_RUNNING */, NG_DEV_MODE && errorMessage);
}
let componentFactory;
if (isComponentFactory) {
componentFactory = componentOrFactory;
}
else {
const resolver = this._injector.get(ComponentFactoryResolver);
componentFactory = resolver.resolveComponentFactory(componentOrFactory);
}
this.componentTypes.push(componentFactory.componentType);
// Create a factory associated with the current module if it's not bound to some other
const ngModule = isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef);
const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);
const nativeElement = compRef.location.nativeElement;
const testability = compRef.injector.get(TESTABILITY, null);
testability?.registerApplication(nativeElement);
compRef.onDestroy(() => {
this.detachView(compRef.hostView);
remove(this.components, compRef);
testability?.unregisterApplication(nativeElement);
});
this._loadComponent(compRef);
if (typeof ngDevMode === 'undefined' || ngDevMode) {
const _console = this._injector.get(Console);
_console.log(`Angular is running in development mode. Call enableProdMode() to enable production mode.`);
}
return compRef;
}
/**
* Invoke this method to explicitly process change detection and its side-effects.
*
* In development mode, `tick()` also performs a second change detection cycle to ensure that no
* further changes are detected. If additional changes are picked up during this second cycle,
* bindings in the app have side-effects that cannot be resolved in a single change detection
* pass.
* In this case, Angular throws an error, since an Angular application can only have one change
* detection pass during which all change detection must complete.
*/
tick() {
NG_DEV_MODE && this.warnIfDestroyed();
if (this._runningTick) {
throw new RuntimeError(101 /* RuntimeErrorCode.RECURSIVE_APPLICATION_REF_TICK */, ngDevMode && 'ApplicationRef.tick is called recursively');
}
try {
this._runningTick = true;
for (let view of this._views) {
view.detectChanges();
}
if (typeof ngDevMode === 'undefined' || ngDevMode) {
for (let view of this._views) {
view.checkNoChanges();
}
}
}
catch (e) {
// Attention: Don't rethrow as it could cancel subscriptions to Observables!
this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e));
}
finally {
this._runningTick = false;
}
}
/**
* Attaches a view so that it will be dirty checked.
* The view will be automatically detached when it is destroyed.
* This will throw if the view is already attached to a ViewContainer.
*/
attachView(viewRef) {
NG_DEV_MODE && this.warnIfDestroyed();
const view = viewRef;
this._views.push(view);
view.attachToAppRef(this);
}
/**
* Detaches a view from dirty checking again.
*/
detachView(viewRef) {
NG_DEV_MODE && this.warnIfDestroyed();
const view = viewRef;
remove(this._views, view);
view.detachFromAppRef();
}
_loadComponent(componentRef) {
this.attachView(componentRef.hostView);
this.tick();
this.components.push(componentRef);
// Get the listeners lazily to prevent DI cycles.
const listeners = this._injector.get(APP_BOOTSTRAP_LISTENER, []);
if (ngDevMode && !Array.isArray(listeners)) {
throw new RuntimeError(-209 /* RuntimeErrorCode.INVALID_MULTI_PROVIDER */, 'Unexpected type of the `APP_BOOTSTRAP_LISTENER` token value ' +
`(expected an array, but got ${typeof listeners}). ` +
'Please check that the `APP_BOOTSTRAP_LISTENER` token is configured as a ' +
'`multi: true` provider.');
}
listeners.push(...this._bootstrapListeners);
listeners.forEach((listener) => listener(componentRef));
}
/** @internal */
ngOnDestroy() {
if (this._destroyed)
return;
try {
// Call all the lifecycle hooks.
this._destroyListeners.forEach(listener => listener());
// Destroy all registered views.
this._views.slice().forEach((view) => view.destroy());
this._onMicrotaskEmptySubscription.unsubscribe();
}
finally {
// Indicate that this instance is destroyed.
this._destroyed = true;
// Release all references.
this._views = [];
this._bootstrapListeners = [];
this._destroyListeners = [];
}
}
/**
* Registers a listener to be called when an instance is destroyed.
*
* @param callback A callback function to add as a listener.
* @returns A function which unregisters a listener.
*
* @internal
*/
onDestroy(callback) {
NG_DEV_MODE && this.warnIfDestroyed();
this._destroyListeners.push(callback);
return () => remove(this._destroyListeners, callback);
}
/**
* Destroys an Angular application represented by this `ApplicationRef`. Calling this function
* will destroy the associated environment injectors as well as all the bootstrapped components
* with their views.
*/
destroy() {
if (this._destroyed) {
throw new RuntimeError(406 /* RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED */, ngDevMode && 'This instance of the `ApplicationRef` has already been destroyed.');
}
const injector = this._injector;
// Check that this injector instance supports destroy operation.
if (injector.destroy && !injector.destroyed) {
// Destroying an underlying injector will trigger the `ngOnDestroy` lifecycle
// hook, which invokes the remaining cleanup actions.
injector.destroy();
}
}
/**
* Returns the number of attached views.
*/
get viewCount() {
return this._views.length;
}
warnIfDestroyed() {
if (NG_DEV_MODE && this._destroyed) {
console.warn(formatRuntimeError(406 /* RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED */, 'This instance of the `ApplicationRef` has already been destroyed.'));
}
}
}
ApplicationRef.ɵfac = function ApplicationRef_Factory(t) { return new (t || ApplicationRef)(i0.ɵɵinject(i2.NgZone), i0.ɵɵinject(i3.EnvironmentInjector), i0.ɵɵinject(i4.ErrorHandler)); };
ApplicationRef.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ApplicationRef, factory: ApplicationRef.ɵfac, providedIn: 'root' });
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.setClassMetadata(ApplicationRef, [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], function () { return [{ type: i2.NgZone }, { type: i3.EnvironmentInjector }, { type: i4.ErrorHandler }]; }, null); })();
function remove(list, el) {
const index = list.indexOf(el);
if (index > -1) {
list.splice(index, 1);
}
}
function _lastDefined(args) {
for (let i = args.length - 1; i >= 0; i--) {
if (args[i] !== undefined) {
return args[i];
}
}
return undefined;
}
function _mergeArrays(parts) {
const result = [];
parts.forEach((part) => part && result.push(...part));
return result;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb25fcmVmLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29yZS9zcmMvYXBwbGljYXRpb25fcmVmLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sb0JBQW9CLENBQUM7QUFFNUIsT0FBTyxFQUFDLEtBQUssRUFBRSxVQUFVLEVBQXlCLE1BQU0sTUFBTSxDQUFDO0FBQy9ELE9BQU8sRUFBQyxLQUFLLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUVyQyxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUN6RCxPQUFPLEVBQUMsc0JBQXNCLEVBQUUsb0JBQW9CLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRixPQUFPLEVBQUMsaUJBQWlCLEVBQW1CLE1BQU0sNEJBQTRCLENBQUM7QUFDL0UsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQ3BELE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFFdkMsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDckQsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLFlBQVksQ0FBQztBQUMxQyxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDN0MsT0FBTyxFQUFDLGtCQUFrQixFQUFFLFlBQVksRUFBbUIsTUFBTSxVQUFVLENBQUM7QUFDNUUsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDdEQsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV4QyxPQUFPLEVBQUMsZ0JBQWdCLEVBQWtCLE1BQU0s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