UNPKG

@angular/core

Version:

Angular - the core framework

997 lines 140 kB
/** * @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 { setThrowInvalidWriteToSignalError } from '@angular/core/primitives/signals'; import { of } from 'rxjs'; import { distinctUntilChanged, first, share, switchMap } from 'rxjs/operators'; import { ApplicationInitStatus } from './application_init'; import { PLATFORM_INITIALIZER } from './application_tokens'; import { getCompilerFacade } from './compiler/compiler_facade'; import { Console } from './console'; import { ENVIRONMENT_INITIALIZER, inject, makeEnvironmentProviders } from './di'; 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 { ImagePerformanceWarning } from './image_performance_warning'; import { InitialRenderPendingTasks } from './initial_render_pending_tasks'; 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 { createNgModuleRefWithProviders, EnvironmentNgModuleRefAdapter, 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 { stringify } from './util/stringify'; import { isStableFactory, NgZone, NoopNgZone, ZONE_IS_STABLE_OBSERVABLE } from './zone/ng_zone'; import * as i0 from "./r3_symbols"; import * as i1 from "./di/injector"; 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'); /** * A [DI token](guide/glossary#di-token "DI token definition") that provides a set of callbacks to * be called for every component that is bootstrapped. * * Each callback must take a `ComponentRef` instance and return nothing. * * `(componentRef: ComponentRef) => void` * * @publicApi */ export const APP_BOOTSTRAP_LISTENER = new InjectionToken('appBootstrapListener'); 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 = compilerOptions.flatMap((option) => option.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(); } /** * Sets the error for an invalid write to a signal to be an Angular `RuntimeError`. */ export function publishSignalConfiguration() { setThrowInvalidWriteToSignalError(() => { throw new RuntimeError(600 /* RuntimeErrorCode.SIGNAL_WRITE_FROM_ILLEGAL_CONTEXT */, ngDevMode && 'Writing to signals is not allowed in a `computed` or an `effect` by default. ' + 'Use `allowSignalWrites` in the `CreateEffectOptions` to enable this inside effects.'); }); } export function isBoundToModule(cf) { return cf.isBoundToModule; } /** * A token for third-party components that can register themselves with NgProbe. * * @deprecated * @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(); publishSignalConfiguration(); _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. */ 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; publishDefaultGlobalUtils(); // Otherwise, setup a new platform injector and run platform initializers. const injector = createPlatformInjector(providers); _platformInjector = injector; publishSignalConfiguration(); runPlatformInitializers(injector); return injector; } function runPlatformInitializers(injector) { const inits = injector.get(PLATFORM_INITIALIZER, null); 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) { try { const { rootComponent, appProviders, platformProviders } = config; if ((typeof ngDevMode === 'undefined' || ngDevMode) && rootComponent !== undefined) { assertStandaloneComponentType(rootComponent); } const platformInjector = createOrReusePlatformInjector(platformProviders); // 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 = [ provideZoneChangeDetection(), ...(appProviders || []), ]; const adapter = new EnvironmentNgModuleRefAdapter({ providers: allAppProviders, parent: platformInjector, debugName: (typeof ngDevMode === 'undefined' || ngDevMode) ? 'Environment Injector' : '', // We skip environment initializers because we need to run them inside the NgZone, which // happens after we get the NgZone instance from the Injector. runEnvironmentInitializers: false, }); const envInjector = adapter.injector; const ngZone = envInjector.get(NgZone); return ngZone.run(() => { envInjector.resolveInjectorInitializers(); const exceptionHandler = envInjector.get(ErrorHandler, null); if ((typeof ngDevMode === 'undefined' || ngDevMode) && !exceptionHandler) { throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, '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); } if (typeof ngDevMode === 'undefined' || ngDevMode) { const imagePerformanceService = envInjector.get(ImagePerformanceWarning); imagePerformanceService.start(); } return appRef; }); }); }); } catch (e) { return Promise.reject(e); } } /** * 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({ eventCoalescing: options?.ngZoneEventCoalescing, runCoalescing: options?.ngZoneRunCoalescing })); // 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 moduleRef = createNgModuleRefWithProviders(moduleFactory.moduleType, this.injector, internalProvideZoneChangeDetection(() => ngZone)); if ((typeof ngDevMode === 'undefined' || ngDevMode) && moduleRef.injector.get(PROVIDED_NG_ZONE, null) !== null) { throw new RuntimeError(207 /* RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT */, '`bootstrapModule` does not support `provideZoneChangeDetection`. Use `BootstrapOptions` instead.'); } const exceptionHandler = moduleRef.injector.get(ErrorHandler, null); if ((typeof ngDevMode === 'undefined' || ngDevMode) && exceptionHandler === null) { throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, '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; } static { this.ɵfac = function PlatformRef_Factory(t) { return new (t || PlatformRef)(i0.ɵɵinject(i1.Injector)); }; } static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PlatformRef, factory: PlatformRef.ɵfac, providedIn: 'platform' }); } } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.setClassMetadata(PlatformRef, [{ type: Injectable, args: [{ providedIn: 'platform' }] }], () => [{ 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?.eventCoalescing ?? false, shouldCoalesceRunChangeDetection: options?.runCoalescing ?? false, }; } function getNgZone(ngZoneToUse = 'zone.js', options) { if (ngZoneToUse === 'noop') { return new NoopNgZone(); } if (ngZoneToUse === 'zone.js') { return new NgZone(options); } return ngZoneToUse; } 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)) { return objs.reduce(optionsReducer, dst); } return { ...dst, ...objs }; } /** * 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 { constructor() { /** @internal */ this._bootstrapListeners = []; this._runningTick = false; this._destroyed = false; this._destroyListeners = []; /** @internal */ this._views = []; this.internalErrorHandler = inject(INTERNAL_APPLICATION_ERROR_HANDLER); this.zoneIsStable = inject(ZONE_IS_STABLE_OBSERVABLE); /** * 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 = []; /** * Returns an Observable that indicates when the application is stable or unstable. */ this.isStable = inject(InitialRenderPendingTasks) .hasPendingTasks.pipe(switchMap(hasPendingTasks => hasPendingTasks ? of(false) : this.zoneIsStable), distinctUntilChanged(), share()); this._injector = inject(EnvironmentInjector); } /** * Indicates whether this instance was destroyed. */ get destroyed() { return this._destroyed; } /** * The `EnvironmentInjector` used to create this application. */ get injector() { return this._injector; } /** * 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) { (typeof ngDevMode === 'undefined' || ngDevMode) && 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 */, (typeof ngDevMode === 'undefined' || ngDevMode) && 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.`); } 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() { (typeof ngDevMode === 'undefined' || ngDevMode) && 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.internalErrorHandler(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) { (typeof ngDevMode === 'undefined' || ngDevMode) && this.warnIfDestroyed(); const view = viewRef; this._views.push(view); view.attachToAppRef(this); } /** * Detaches a view from dirty checking again. */ detachView(viewRef) { (typeof ngDevMode === 'undefined' || ngDevMode) && 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.'); } [...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()); } 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. */ onDestroy(callback) { (typeof ngDevMode === 'undefined' || ngDevMode) && 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 ((typeof ngDevMode === 'undefined' || ngDevMode) && this._destroyed) { console.warn(formatRuntimeError(406 /* RuntimeErrorCode.APPLICATION_REF_ALREADY_DESTROYED */, 'This instance of the `ApplicationRef` has already been destroyed.')); } } static { this.ɵfac = function ApplicationRef_Factory(t) { return new (t || ApplicationRef)(); }; } static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ApplicationRef, factory: ApplicationRef.ɵfac, providedIn: 'root' }); } } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.setClassMetadata(ApplicationRef, [{ type: Injectable, args: [{ providedIn: 'root' }] }], null, 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; } /** * `InjectionToken` used to configure how to call the `ErrorHandler`. * * `NgZone` is provided by default today so the default (and only) implementation for this * is calling `ErrorHandler.handleError` outside of the Angular zone. */ const INTERNAL_APPLICATION_ERROR_HANDLER = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'internal error handler' : '', { providedIn: 'root', factory: () => { const userErrorHandler = inject(ErrorHandler); return userErrorHandler.handleError.bind(this); } }); function ngZoneApplicationErrorHandlerFactory() { const zone = inject(NgZone); const userErrorHandler = inject(ErrorHandler); return (e) => zone.runOutsideAngular(() => userErrorHandler.handleError(e)); } export class NgZoneChangeDetectionScheduler { constructor() { this.zone = inject(NgZone); this.applicationRef = inject(ApplicationRef); } initialize() { if (this._onMicrotaskEmptySubscription) { return; } this._onMicrotaskEmptySubscription = this.zone.onMicrotaskEmpty.subscribe({ next: () => { this.zone.run(() => { this.applicationRef.tick(); }); } }); } ngOnDestroy() { this._onMicrotaskEmptySubscription?.unsubscribe(); } static { this.ɵfac = function NgZoneChangeDetectionScheduler_Factory(t) { return new (t || NgZoneChangeDetectionScheduler)(); }; } static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: NgZoneChangeDetectionScheduler, factory: NgZoneChangeDetectionScheduler.ɵfac, providedIn: 'root' }); } } (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.setClassMetadata(NgZoneChangeDetectionScheduler, [{ type: Injectable, args: [{ providedIn: 'root' }] }], null, null); })(); /** * Internal token used to verify that `provideZoneChangeDetection` is not used * with the bootstrapModule API. */ const PROVIDED_NG_ZONE = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'provideZoneChangeDetection token' : ''); export function internalProvideZoneChangeDetection(ngZoneFactory) { return [ { provide: NgZone, useFactory: ngZoneFactory }, { provide: ENVIRONMENT_INITIALIZER, multi: true, useFactory: () => { const ngZoneChangeDetectionScheduler = inject(NgZoneChangeDetectionScheduler, { optional: true }); if ((typeof ngDevMode === 'undefined' || ngDevMode) && ngZoneChangeDetectionScheduler === null) { throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, `A required Injectable was not found in the dependency injection tree. ` + 'If you are bootstrapping an NgModule, make sure that the `BrowserModule` is imported.'); } return () => ngZoneChangeDetectionScheduler.initialize(); }, }, { provide: INTERNAL_APPLICATION_ERROR_HANDLER, useFactory: ngZoneApplicationErrorHandlerFactory }, { provide: ZONE_IS_STABLE_OBSERVABLE, useFactory: isStableFactory }, ]; } /** * Provides `NgZone`-based change detection for the application bootstrapped using * `bootstrapApplication`. * * `NgZone` is already provided in applications by default. This provider allows you to configure * options like `eventCoalescing` in the `NgZone`. * This provider is not available for `platformBrowser().bootstrapModule`, which uses * `BootstrapOptions` instead. * * @usageNotes * ```typescript * bootstrapApplication(MyApp, {providers: [ * provideZoneChangeDetection({eventCoalescing: true}), * ]}); * ``` * * @publicApi * @see {@link bootstrapApplication} * @see {@link NgZoneOptions} */ export function provideZoneChangeDetection(options) { const zoneProviders = internalProvideZoneChangeDetection(() => new NgZone(getNgZoneOptions(options))); return makeEnvironmentProviders([ (typeof ngDevMode === 'undefined' || ngDevMode) ? { provide: PROVIDED_NG_ZONE, useValue: true } : [], zoneProviders, ]); } let whenStableStore; /** * Returns a Promise that resolves when the application becomes stable after this method is called * the first time. */ export function whenStable(applicationRef) { whenStableStore ??= new WeakMap(); const cachedWhenStable = whenStableStore.get(applicationRef); if (cachedWhenStable) { return cachedWhenStable; } const whenStablePromise = applicationRef.isStable.pipe(first((isStable) => isStable)).toPromise().then(() => void 0); whenStableStore.set(applicationRef, whenStablePromise); // Be a good citizen and clean the store `onDestroy` even though we are using `WeakMap`. applicationRef.onDestroy(() => whenStableStore?.delete(applicationRef)); return whenStablePromise; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb25fcmVmLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29yZS9zcmMvYXBwbGljYXRpb25fcmVmLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sb0JBQW9CLENBQUM7QUFFNUIsT0FBTyxFQUFDLGlDQUFpQyxFQUFDLE1BQU0sa0NBQWtDLENBQUM7QUFDbkYsT0FBTyxFQUFhLEVBQUUsRUFBZSxNQUFNLE1BQU0sQ0FBQztBQUNsRCxPQUFPLEVBQUMsb0JBQW9CLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU3RSxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUN6RCxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUMxRCxPQUFPLEVBQUMsaUJBQWlCLEVBQW1CLE1BQU0sNEJBQTRCLENBQUM7QUFDL0UsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEVBQUMsdUJBQXVCLEVBQUUsTUFBTSxFQUFFLHdCQUF3QixFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQy9FLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUMzQyxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDcEQsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV2QyxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUNyRCxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQzFDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM3QyxPQUFPLEVBQUMsa0JBQWtCLEVBQUUsWUFBWSxFQUFtQixNQUFNLFVBQVUsQ0FBQztB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